From 09649ce64b4e8c00ea64209002fcd3fda8028e71 Mon Sep 17 00:00:00 2001
From: Marci W <333176+marciw@users.noreply.github.com>
Date: Fri, 7 Mar 2025 00:21:27 -0500
Subject: [PATCH 01/57] fix external links (#2826) (#2827)
(cherry picked from commit 9ac0b0afdf80946135581d086ee9f4603f4af99e)
Co-authored-by: Colleen McGinnis
---
docs/reference/client-helpers.md | 2 +-
docs/reference/connecting.md | 4 ++--
docs/reference/opentelemetry.md | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/docs/reference/client-helpers.md b/docs/reference/client-helpers.md
index 02ab4e026..904d61815 100644
--- a/docs/reference/client-helpers.md
+++ b/docs/reference/client-helpers.md
@@ -5,7 +5,7 @@ mapped_pages:
# Client helpers [client-helpers]
-You can find here a collection of simple helper functions that abstract some specifics of the raw API. For detailed examples, refer to [this page](https://elasticsearch-py.readthedocs.io/en/stable/helpers.md).
+You can find here a collection of simple helper functions that abstract some specifics of the raw API. For detailed examples, refer to [this page](https://elasticsearch-py.readthedocs.io/en/stable/helpers.html).
## Bulk helpers [bulk-helpers]
diff --git a/docs/reference/connecting.md b/docs/reference/connecting.md
index aefc50b1f..27f7fecbc 100644
--- a/docs/reference/connecting.md
+++ b/docs/reference/connecting.md
@@ -352,6 +352,6 @@ def main(request: func.HttpRequest) -> func.HttpResponse:
Resources used to assess these recommendations:
* [GCP Cloud Functions: Tips & Tricks](https://cloud.google.com/functions/docs/bestpractices/tips#use_global_variables_to_reuse_objects_in_future_invocations)
-* [Best practices for working with AWS Lambda functions](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.md)
+* [Best practices for working with AWS Lambda functions](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html)
* [Azure Functions Python developer guide](https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-python?tabs=azurecli-linux%2Capplication-level#global-variables)
-* [AWS Lambda: Comparing the effect of global scope](https://docs.aws.amazon.com/lambda/latest/operatorguide/global-scope.md)
+* [AWS Lambda: Comparing the effect of global scope](https://docs.aws.amazon.com/lambda/latest/operatorguide/global-scope.html)
diff --git a/docs/reference/opentelemetry.md b/docs/reference/opentelemetry.md
index fb117d505..2b6b1eec2 100644
--- a/docs/reference/opentelemetry.md
+++ b/docs/reference/opentelemetry.md
@@ -41,7 +41,7 @@ When using the [manual Python OpenTelemetry instrumentation](https://opentelemet
## Comparison with community instrumentation [_comparison_with_community_instrumentation]
-The [commmunity OpenTelemetry Elasticsearch instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/elasticsearch/elasticsearch.md) also instruments the client and sends OpenTelemetry traces, but was developed before the OpenTelemetry Semantic Conventions for {{es}}, so the traces attributes are inconsistent with other OpenTelemetry Elasticsearch client instrumentations. To avoid tracing the same requests twice, make sure to use only one instrumentation, either by uninstalling the opentelemetry-instrumentation-elasticsearch Python package or by [disabling the native instrumentation](#opentelemetry-config-enable).
+The [commmunity OpenTelemetry Elasticsearch instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/elasticsearch/elasticsearch.html) also instruments the client and sends OpenTelemetry traces, but was developed before the OpenTelemetry Semantic Conventions for {{es}}, so the traces attributes are inconsistent with other OpenTelemetry Elasticsearch client instrumentations. To avoid tracing the same requests twice, make sure to use only one instrumentation, either by uninstalling the opentelemetry-instrumentation-elasticsearch Python package or by [disabling the native instrumentation](#opentelemetry-config-enable).
### Configuring the OpenTelemetry instrumentation [_configuring_the_opentelemetry_instrumentation]
From 3910e1ad3057fafba1141a7d8023b545f11de8b0 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 7 Mar 2025 10:06:09 +0400
Subject: [PATCH 02/57] Delete docs-preview.yml (#2828) (#2829)
(cherry picked from commit b59f2fc926cbc0de618bfef2b53e81e7f4d135ef)
Co-authored-by: Marci W <333176+marciw@users.noreply.github.com>
---
.github/workflows/docs-preview.yml | 20 --------------------
1 file changed, 20 deletions(-)
delete mode 100644 .github/workflows/docs-preview.yml
diff --git a/.github/workflows/docs-preview.yml b/.github/workflows/docs-preview.yml
deleted file mode 100644
index 40d7b7208..000000000
--- a/.github/workflows/docs-preview.yml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: docs-preview
-
-on:
- pull_request_target:
- types: [opened]
-
-permissions:
- pull-requests: write
-
-jobs:
- doc-preview-pr:
- runs-on: ubuntu-latest
- steps:
- - uses: elastic/docs/.github/actions/docs-preview@master
- with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- repo: ${{ github.event.repository.name }}
- preview-path: 'guide/en/elasticsearch/client/python-api/index.html'
- pr: ${{ github.event.pull_request.number }}
From 6eb283e5625d3156dddc2c6d55819ad0e6cb8951 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 7 Mar 2025 10:59:21 +0400
Subject: [PATCH 03/57] Fix logo URL (#2825) (#2830)
(cherry picked from commit 922020165c3f3e57571682cce15404ddf22c88eb)
Co-authored-by: Quentin Pradet
---
README.md | 2 +-
docs/images/logo-elastic-glyph-color.svg | 16 ++++++++++++++++
2 files changed, 17 insertions(+), 1 deletion(-)
create mode 100644 docs/images/logo-elastic-glyph-color.svg
diff --git a/README.md b/README.md
index eb242a90c..20b72407d 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
Each context requires a script, but additional parameters depend on the context you're using for that script.
- ``_
+ ``_
:param context: The context that the script should run in. NOTE: Result ordering
in the field contexts is not guaranteed.
diff --git a/elasticsearch/_async/client/connector.py b/elasticsearch/_async/client/connector.py
index debf9e3ce..3a55163bb 100644
--- a/elasticsearch/_async/client/connector.py
+++ b/elasticsearch/_async/client/connector.py
@@ -1539,7 +1539,7 @@ async def update_filtering_validation(
Update the draft filtering validation info for a connector.
- ``_
+ ``_
:param connector_id: The unique identifier of the connector to be updated
:param validation:
@@ -1710,7 +1710,7 @@ async def update_native(
Update the connector is_native flag.
- ``_
+ ``_
:param connector_id: The unique identifier of the connector to be updated
:param is_native:
diff --git a/elasticsearch/_async/client/esql.py b/elasticsearch/_async/client/esql.py
index 0df836730..dca7ca2bb 100644
--- a/elasticsearch/_async/client/esql.py
+++ b/elasticsearch/_async/client/esql.py
@@ -323,7 +323,7 @@ async def async_query_stop(
If the Elasticsearch security features are enabled, only the user who first submitted the ES|QL query can stop it.
- ``_
+ ``_
:param id: The unique identifier of the query. A query ID is provided in the
ES|QL async query API response for a query that does not complete in the
@@ -408,7 +408,7 @@ async def query(
Get search results for an ES|QL (Elasticsearch query language) query.
- ``_
+ ``_
:param query: The ES|QL query API accepts an ES|QL query string in the query
parameter, runs it, and returns the results.
diff --git a/elasticsearch/_async/client/indices.py b/elasticsearch/_async/client/indices.py
index 31ee76bca..ac3f93d8f 100644
--- a/elasticsearch/_async/client/indices.py
+++ b/elasticsearch/_async/client/indices.py
@@ -265,7 +265,7 @@ async def cancel_migrate_reindex(
Cancel a migration reindex attempt for a data stream or index.
- ``_
+ ``_
:param index: The index or data stream name
"""
@@ -794,7 +794,7 @@ async def create_from(
Copy the mappings and settings from the source index to a destination index while allowing request settings and mappings to override the source values.
- ``_
+ ``_
:param source: The source index or data stream name
:param dest: The destination index or data stream name
@@ -2487,6 +2487,7 @@ async def get_field_mapping(
human: t.Optional[bool] = None,
ignore_unavailable: t.Optional[bool] = None,
include_defaults: t.Optional[bool] = None,
+ local: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
) -> ObjectApiResponse[t.Any]:
"""
@@ -2515,6 +2516,8 @@ async def get_field_mapping(
:param ignore_unavailable: If `false`, the request returns an error if it targets
a missing or closed index.
:param include_defaults: If `true`, return all default settings in the response.
+ :param local: If `true`, the request retrieves information from the local node
+ only.
"""
if fields in SKIP_IN_PATH:
raise ValueError("Empty value passed for parameter 'fields'")
@@ -2542,6 +2545,8 @@ async def get_field_mapping(
__query["ignore_unavailable"] = ignore_unavailable
if include_defaults is not None:
__query["include_defaults"] = include_defaults
+ if local is not None:
+ __query["local"] = local
if pretty is not None:
__query["pretty"] = pretty
__headers = {"accept": "application/json"}
@@ -2726,7 +2731,7 @@ async def get_migrate_reindex_status(
Get the status of a migration reindex attempt for a data stream or index.
- ``_
+ ``_
:param index: The index or data stream name.
"""
@@ -2945,7 +2950,7 @@ async def migrate_reindex(
The persistent task ID is returned immediately and the reindexing work is completed in that task.
- ``_
+ ``_
:param reindex:
"""
@@ -3006,7 +3011,7 @@ async def migrate_to_data_stream(
The write index for the alias becomes the write index for the stream.
- ``_
+ ``_
:param name: Name of the index alias to convert to a data stream.
:param master_timeout: Period to wait for a connection to the master node. If
@@ -3062,7 +3067,7 @@ async def modify_data_stream(
Performs one or more data stream modification actions in a single atomic operation.
- ``_
+ ``_
:param actions: Actions to perform.
"""
@@ -3227,7 +3232,7 @@ async def promote_data_stream(
This will affect the lifecycle management of the data stream and interfere with the data stream size and retention.
- ``_
+ ``_
:param name: The name of the data stream
:param master_timeout: Period to wait for a connection to the master node. If
@@ -3293,7 +3298,7 @@ async def put_alias(
Adds a data stream or index to an alias.
- ``_
+ ``_
:param index: Comma-separated list of data streams or indices to add. Supports
wildcards (`*`). Wildcard patterns that match both data streams and indices
@@ -3400,7 +3405,7 @@ async def put_data_lifecycle(
Update the data stream lifecycle of the specified data streams.
- ``_
+ ``_
:param name: Comma-separated list of data streams used to limit the request.
Supports wildcards (`*`). To target all data streams use `*` or `_all`.
@@ -3528,7 +3533,7 @@ async def put_index_template(
If an entry already exists with the same key, then it is overwritten by the new definition.
- ``_
+ ``_
:param name: Index or template name
:param allow_auto_create: This setting overrides the value of the `action.auto_create_index`
@@ -5372,7 +5377,7 @@ async def update_aliases(
Adds a data stream or index to an alias.
- ``_
+ ``_
:param actions: Actions to perform.
:param master_timeout: Period to wait for a connection to the master node. If
@@ -5451,7 +5456,7 @@ async def validate_query(
Validates a query without running it.
- ``_
+ ``_
:param index: Comma-separated list of data streams, indices, and aliases to search.
Supports wildcards (`*`). To search all data streams or indices, omit this
diff --git a/elasticsearch/_async/client/inference.py b/elasticsearch/_async/client/inference.py
index 54dd0d32b..e685d1c5c 100644
--- a/elasticsearch/_async/client/inference.py
+++ b/elasticsearch/_async/client/inference.py
@@ -25,6 +25,74 @@
class InferenceClient(NamespacedClient):
+ @_rewrite_parameters(
+ body_fields=("input", "task_settings"),
+ )
+ async def completion(
+ self,
+ *,
+ inference_id: str,
+ input: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Any] = None,
+ timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Perform completion inference on the service
+
+
+ ``_
+
+ :param inference_id: The inference Id
+ :param input: Inference input. Either a string or an array of strings.
+ :param task_settings: Optional task settings
+ :param timeout: Specifies the amount of time to wait for the inference request
+ to complete.
+ """
+ if inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'inference_id'")
+ if input is None and body is None:
+ raise ValueError("Empty value passed for parameter 'input'")
+ __path_parts: t.Dict[str, str] = {"inference_id": _quote(inference_id)}
+ __path = f'/_inference/completion/{__path_parts["inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if timeout is not None:
+ __query["timeout"] = timeout
+ if not __body:
+ if input is not None:
+ __body["input"] = input
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "POST",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.completion",
+ path_parts=__path_parts,
+ )
+
@_rewrite_parameters()
async def delete(
self,
@@ -33,7 +101,13 @@ async def delete(
task_type: t.Optional[
t.Union[
str,
- t.Literal["completion", "rerank", "sparse_embedding", "text_embedding"],
+ t.Literal[
+ "chat_completion",
+ "completion",
+ "rerank",
+ "sparse_embedding",
+ "text_embedding",
+ ],
]
] = None,
dry_run: t.Optional[bool] = None,
@@ -102,7 +176,13 @@ async def get(
task_type: t.Optional[
t.Union[
str,
- t.Literal["completion", "rerank", "sparse_embedding", "text_embedding"],
+ t.Literal[
+ "chat_completion",
+ "completion",
+ "rerank",
+ "sparse_embedding",
+ "text_embedding",
+ ],
]
] = None,
inference_id: t.Optional[str] = None,
@@ -155,24 +235,188 @@ async def get(
)
@_rewrite_parameters(
- body_fields=("input", "query", "task_settings"),
+ body_name="inference_config",
)
- async def inference(
+ async def put(
self,
*,
inference_id: str,
- input: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ inference_config: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Mapping[str, t.Any]] = None,
task_type: t.Optional[
t.Union[
str,
- t.Literal["completion", "rerank", "sparse_embedding", "text_embedding"],
+ t.Literal[
+ "chat_completion",
+ "completion",
+ "rerank",
+ "sparse_embedding",
+ "text_embedding",
+ ],
]
] = None,
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an inference endpoint.
+ When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
IMPORTANT: The inference APIs enable you to use certain services, such as built-in machine learning models (ELSER, E5), models uploaded through Eland, Cohere, OpenAI, Mistral, Azure OpenAI, Google AI Studio, Google Vertex AI, Anthropic, Watsonx.ai, or Hugging Face.
+ For built-in models and models uploaded through Eland, the inference APIs offer an alternative way to use and manage trained models.
+ However, if you do not plan to use the inference APIs to use these models or if you want to use non-NLP models, use the machine learning trained model APIs.
+
+
+ ``_
+
+ :param inference_id: The inference Id
+ :param inference_config:
+ :param task_type: The task type
+ """
+ if inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'inference_id'")
+ if inference_config is None and body is None:
+ raise ValueError(
+ "Empty value passed for parameters 'inference_config' and 'body', one of them should be set."
+ )
+ elif inference_config is not None and body is not None:
+ raise ValueError("Cannot set both 'inference_config' and 'body'")
+ __path_parts: t.Dict[str, str]
+ if task_type not in SKIP_IN_PATH and inference_id not in SKIP_IN_PATH:
+ __path_parts = {
+ "task_type": _quote(task_type),
+ "inference_id": _quote(inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["inference_id"]}'
+ elif inference_id not in SKIP_IN_PATH:
+ __path_parts = {"inference_id": _quote(inference_id)}
+ __path = f'/_inference/{__path_parts["inference_id"]}'
+ else:
+ raise ValueError("Couldn't find a path for the given parameters")
+ __query: t.Dict[str, t.Any] = {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ __body = inference_config if inference_config is not None else body
+ __headers = {"accept": "application/json", "content-type": "application/json"}
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("service", "service_settings"),
+ )
+ async def put_watsonx(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["text_embedding"]],
+ watsonx_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["watsonxai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create a Watsonx inference endpoint.
+
Creates an inference endpoint to perform an inference task with the watsonxai service.
+ You need an IBM Cloud Databases for Elasticsearch deployment to use the watsonxai inference service.
+ You can provision one through the IBM catalog, the Cloud Databases CLI plug-in, the Cloud Databases API, or Terraform.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The task type. The only valid task type for the model to perform
+ is `text_embedding`.
+ :param watsonx_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `watsonxai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `watsonxai` service.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if watsonx_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'watsonx_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "watsonx_inference_id": _quote(watsonx_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["watsonx_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_watsonx",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("input", "query", "task_settings"),
+ )
+ async def rerank(
+ self,
+ *,
+ inference_id: str,
+ input: t.Optional[t.Union[str, t.Sequence[str]]] = None,
query: t.Optional[str] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
task_settings: t.Optional[t.Any] = None,
timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
body: t.Optional[t.Dict[str, t.Any]] = None,
@@ -180,14 +424,7 @@ async def inference(
"""
.. raw:: html
-
Perform inference on the service.
-
This API enables you to use machine learning models to perform specific tasks on data that you provide as an input.
- It returns a response with the results of the tasks.
- The inference endpoint you use can perform one specific task that has been defined when the endpoint was created with the create inference API.
-
-
info
- The inference APIs enable you to use certain services, such as built-in machine learning models (ELSER, E5), models uploaded through Eland, Cohere, OpenAI, Azure, Google AI Studio, Google Vertex AI, Anthropic, Watsonx.ai, or Hugging Face. For built-in models and models uploaded through Eland, the inference APIs offer an alternative way to use and manage trained models. However, if you do not plan to use the inference APIs to use these models or if you want to use non-NLP models, use the machine learning trained model APIs.
-
+
Perform rereanking inference on the service
``_
@@ -196,9 +433,7 @@ async def inference(
:param input: The text on which you want to perform the inference task. It can
be a single string or an array. > info > Inference endpoints for the `completion`
task type currently only support a single string as input.
- :param task_type: The type of inference task that the model performs.
- :param query: The query input, which is required only for the `rerank` task.
- It is not required for other tasks.
+ :param query: Query input.
:param task_settings: Task settings for the individual inference request. These
settings are specific to the task type you specified and override the task
settings specified when initializing the service.
@@ -208,18 +443,10 @@ async def inference(
raise ValueError("Empty value passed for parameter 'inference_id'")
if input is None and body is None:
raise ValueError("Empty value passed for parameter 'input'")
- __path_parts: t.Dict[str, str]
- if task_type not in SKIP_IN_PATH and inference_id not in SKIP_IN_PATH:
- __path_parts = {
- "task_type": _quote(task_type),
- "inference_id": _quote(inference_id),
- }
- __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["inference_id"]}'
- elif inference_id not in SKIP_IN_PATH:
- __path_parts = {"inference_id": _quote(inference_id)}
- __path = f'/_inference/{__path_parts["inference_id"]}'
- else:
- raise ValueError("Couldn't find a path for the given parameters")
+ if query is None and body is None:
+ raise ValueError("Empty value passed for parameter 'query'")
+ __path_parts: t.Dict[str, str] = {"inference_id": _quote(inference_id)}
+ __path = f'/_inference/rerank/{__path_parts["inference_id"]}'
__query: t.Dict[str, t.Any] = {}
__body: t.Dict[str, t.Any] = body if body is not None else {}
if error_trace is not None:
@@ -250,71 +477,48 @@ async def inference(
params=__query,
headers=__headers,
body=__body,
- endpoint_id="inference.inference",
+ endpoint_id="inference.rerank",
path_parts=__path_parts,
)
@_rewrite_parameters(
- body_name="inference_config",
+ body_fields=("input", "task_settings"),
)
- async def put(
+ async def sparse_embedding(
self,
*,
inference_id: str,
- inference_config: t.Optional[t.Mapping[str, t.Any]] = None,
- body: t.Optional[t.Mapping[str, t.Any]] = None,
- task_type: t.Optional[
- t.Union[
- str,
- t.Literal["completion", "rerank", "sparse_embedding", "text_embedding"],
- ]
- ] = None,
+ input: t.Optional[t.Union[str, t.Sequence[str]]] = None,
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Any] = None,
+ timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
) -> ObjectApiResponse[t.Any]:
"""
.. raw:: html
-
Create an inference endpoint.
- When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
- After creating the endpoint, wait for the model deployment to complete before using it.
- To verify the deployment status, use the get trained model statistics API.
- Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
- Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
-
IMPORTANT: The inference APIs enable you to use certain services, such as built-in machine learning models (ELSER, E5), models uploaded through Eland, Cohere, OpenAI, Mistral, Azure OpenAI, Google AI Studio, Google Vertex AI, Anthropic, Watsonx.ai, or Hugging Face.
- For built-in models and models uploaded through Eland, the inference APIs offer an alternative way to use and manage trained models.
- However, if you do not plan to use the inference APIs to use these models or if you want to use non-NLP models, use the machine learning trained model APIs.
+
Perform sparse embedding inference on the service
- ``_
+ ``_
:param inference_id: The inference Id
- :param inference_config:
- :param task_type: The task type
+ :param input: Inference input. Either a string or an array of strings.
+ :param task_settings: Optional task settings
+ :param timeout: Specifies the amount of time to wait for the inference request
+ to complete.
"""
if inference_id in SKIP_IN_PATH:
raise ValueError("Empty value passed for parameter 'inference_id'")
- if inference_config is None and body is None:
- raise ValueError(
- "Empty value passed for parameters 'inference_config' and 'body', one of them should be set."
- )
- elif inference_config is not None and body is not None:
- raise ValueError("Cannot set both 'inference_config' and 'body'")
- __path_parts: t.Dict[str, str]
- if task_type not in SKIP_IN_PATH and inference_id not in SKIP_IN_PATH:
- __path_parts = {
- "task_type": _quote(task_type),
- "inference_id": _quote(inference_id),
- }
- __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["inference_id"]}'
- elif inference_id not in SKIP_IN_PATH:
- __path_parts = {"inference_id": _quote(inference_id)}
- __path = f'/_inference/{__path_parts["inference_id"]}'
- else:
- raise ValueError("Couldn't find a path for the given parameters")
+ if input is None and body is None:
+ raise ValueError("Empty value passed for parameter 'input'")
+ __path_parts: t.Dict[str, str] = {"inference_id": _quote(inference_id)}
+ __path = f'/_inference/sparse_embedding/{__path_parts["inference_id"]}'
__query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
if error_trace is not None:
__query["error_trace"] = error_trace
if filter_path is not None:
@@ -323,15 +527,93 @@ async def put(
__query["human"] = human
if pretty is not None:
__query["pretty"] = pretty
- __body = inference_config if inference_config is not None else body
- __headers = {"accept": "application/json", "content-type": "application/json"}
+ if timeout is not None:
+ __query["timeout"] = timeout
+ if not __body:
+ if input is not None:
+ __body["input"] = input
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
return await self.perform_request( # type: ignore[return-value]
- "PUT",
+ "POST",
__path,
params=__query,
headers=__headers,
body=__body,
- endpoint_id="inference.put",
+ endpoint_id="inference.sparse_embedding",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("input", "task_settings"),
+ )
+ async def text_embedding(
+ self,
+ *,
+ inference_id: str,
+ input: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Any] = None,
+ timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Perform text embedding inference on the service
+
+
+ ``_
+
+ :param inference_id: The inference Id
+ :param input: Inference input. Either a string or an array of strings.
+ :param task_settings: Optional task settings
+ :param timeout: Specifies the amount of time to wait for the inference request
+ to complete.
+ """
+ if inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'inference_id'")
+ if input is None and body is None:
+ raise ValueError("Empty value passed for parameter 'input'")
+ __path_parts: t.Dict[str, str] = {"inference_id": _quote(inference_id)}
+ __path = f'/_inference/text_embedding/{__path_parts["inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if timeout is not None:
+ __query["timeout"] = timeout
+ if not __body:
+ if input is not None:
+ __body["input"] = input
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "POST",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.text_embedding",
path_parts=__path_parts,
)
@@ -347,7 +629,13 @@ async def update(
task_type: t.Optional[
t.Union[
str,
- t.Literal["completion", "rerank", "sparse_embedding", "text_embedding"],
+ t.Literal[
+ "chat_completion",
+ "completion",
+ "rerank",
+ "sparse_embedding",
+ "text_embedding",
+ ],
]
] = None,
error_trace: t.Optional[bool] = None,
@@ -403,7 +691,7 @@ async def update(
__body = inference_config if inference_config is not None else body
__headers = {"accept": "application/json", "content-type": "application/json"}
return await self.perform_request( # type: ignore[return-value]
- "POST",
+ "PUT",
__path,
params=__query,
headers=__headers,
diff --git a/elasticsearch/_async/client/ingest.py b/elasticsearch/_async/client/ingest.py
index 1cf0cfe1b..27a0f09f3 100644
--- a/elasticsearch/_async/client/ingest.py
+++ b/elasticsearch/_async/client/ingest.py
@@ -208,7 +208,7 @@ async def geo_ip_stats(
Get download statistics for GeoIP2 databases that are used with the GeoIP processor.
- ``_
+ ``_
"""
__path_parts: t.Dict[str, str] = {}
__path = "/_ingest/geoip/stats"
@@ -412,7 +412,7 @@ async def processor_grok(
A grok pattern is like a regular expression that supports aliased expressions that can be reused.
- ``_
+ ``_
"""
__path_parts: t.Dict[str, str] = {}
__path = "/_ingest/processor/grok"
@@ -620,7 +620,7 @@ async def put_pipeline(
Changes made using this API take effect immediately.
- ``_
+ ``_
:param id: ID of the ingest pipeline to create or update.
:param deprecated: Marks this ingest pipeline as deprecated. When a deprecated
diff --git a/elasticsearch/_async/client/ml.py b/elasticsearch/_async/client/ml.py
index 80bc46565..6599c0923 100644
--- a/elasticsearch/_async/client/ml.py
+++ b/elasticsearch/_async/client/ml.py
@@ -2616,7 +2616,6 @@ async def get_trained_models(
],
]
] = None,
- include_model_definition: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
size: t.Optional[int] = None,
tags: t.Optional[t.Union[str, t.Sequence[str]]] = None,
@@ -2646,8 +2645,6 @@ async def get_trained_models(
:param from_: Skips the specified number of models.
:param include: A comma delimited string of optional fields to include in the
response body.
- :param include_model_definition: parameter is deprecated! Use [include=definition]
- instead
:param size: Specifies the maximum number of models to obtain.
:param tags: A comma delimited string of tags. A trained model can have many
tags, or none. When supplied, only trained models that contain all the supplied
@@ -2677,8 +2674,6 @@ async def get_trained_models(
__query["human"] = human
if include is not None:
__query["include"] = include
- if include_model_definition is not None:
- __query["include_model_definition"] = include_model_definition
if pretty is not None:
__query["pretty"] = pretty
if size is not None:
@@ -5733,7 +5728,7 @@ async def validate(
Validate an anomaly detection job.
- ``_
+ ``_
:param analysis_config:
:param analysis_limits:
diff --git a/elasticsearch/_async/client/simulate.py b/elasticsearch/_async/client/simulate.py
index 3c3d33288..bb636ddb6 100644
--- a/elasticsearch/_async/client/simulate.py
+++ b/elasticsearch/_async/client/simulate.py
@@ -35,7 +35,7 @@ class SimulateClient(NamespacedClient):
body_fields=(
"docs",
"component_template_substitutions",
- "index_template_subtitutions",
+ "index_template_substitutions",
"mapping_addition",
"pipeline_substitutions",
),
@@ -52,7 +52,7 @@ async def ingest(
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
- index_template_subtitutions: t.Optional[
+ index_template_substitutions: t.Optional[
t.Mapping[str, t.Mapping[str, t.Any]]
] = None,
mapping_addition: t.Optional[t.Mapping[str, t.Any]] = None,
@@ -90,7 +90,7 @@ async def ingest(
an index argument.
:param component_template_substitutions: A map of component template names to
substitute component template definition objects.
- :param index_template_subtitutions: A map of index template names to substitute
+ :param index_template_substitutions: A map of index template names to substitute
index template definition objects.
:param mapping_addition:
:param pipeline: The pipeline to use as the default pipeline. This value can
@@ -127,8 +127,8 @@ async def ingest(
__body["component_template_substitutions"] = (
component_template_substitutions
)
- if index_template_subtitutions is not None:
- __body["index_template_subtitutions"] = index_template_subtitutions
+ if index_template_substitutions is not None:
+ __body["index_template_substitutions"] = index_template_substitutions
if mapping_addition is not None:
__body["mapping_addition"] = mapping_addition
if pipeline_substitutions is not None:
diff --git a/elasticsearch/_sync/client/__init__.py b/elasticsearch/_sync/client/__init__.py
index 6d9131995..32d736192 100644
--- a/elasticsearch/_sync/client/__init__.py
+++ b/elasticsearch/_sync/client/__init__.py
@@ -3112,7 +3112,7 @@ def knn_search(
- ``_
+ ``_
:param index: A comma-separated list of index names to search; use `_all` or
to perform the operation on all indices.
@@ -4444,7 +4444,7 @@ def scripts_painless_execute(
Each context requires a script, but additional parameters depend on the context you're using for that script.
- ``_
+ ``_
:param context: The context that the script should run in. NOTE: Result ordering
in the field contexts is not guaranteed.
diff --git a/elasticsearch/_sync/client/connector.py b/elasticsearch/_sync/client/connector.py
index fc9b193a1..fe2b931da 100644
--- a/elasticsearch/_sync/client/connector.py
+++ b/elasticsearch/_sync/client/connector.py
@@ -1539,7 +1539,7 @@ def update_filtering_validation(
Update the draft filtering validation info for a connector.
- ``_
+ ``_
:param connector_id: The unique identifier of the connector to be updated
:param validation:
@@ -1710,7 +1710,7 @@ def update_native(
Update the connector is_native flag.
- ``_
+ ``_
:param connector_id: The unique identifier of the connector to be updated
:param is_native:
diff --git a/elasticsearch/_sync/client/esql.py b/elasticsearch/_sync/client/esql.py
index ce9a3a838..7d29224a9 100644
--- a/elasticsearch/_sync/client/esql.py
+++ b/elasticsearch/_sync/client/esql.py
@@ -323,7 +323,7 @@ def async_query_stop(
If the Elasticsearch security features are enabled, only the user who first submitted the ES|QL query can stop it.
- ``_
+ ``_
:param id: The unique identifier of the query. A query ID is provided in the
ES|QL async query API response for a query that does not complete in the
@@ -408,7 +408,7 @@ def query(
Get search results for an ES|QL (Elasticsearch query language) query.
- ``_
+ ``_
:param query: The ES|QL query API accepts an ES|QL query string in the query
parameter, runs it, and returns the results.
diff --git a/elasticsearch/_sync/client/indices.py b/elasticsearch/_sync/client/indices.py
index 4d502f1af..939eeaf29 100644
--- a/elasticsearch/_sync/client/indices.py
+++ b/elasticsearch/_sync/client/indices.py
@@ -265,7 +265,7 @@ def cancel_migrate_reindex(
Cancel a migration reindex attempt for a data stream or index.
- ``_
+ ``_
:param index: The index or data stream name
"""
@@ -794,7 +794,7 @@ def create_from(
Copy the mappings and settings from the source index to a destination index while allowing request settings and mappings to override the source values.
- ``_
+ ``_
:param source: The source index or data stream name
:param dest: The destination index or data stream name
@@ -2487,6 +2487,7 @@ def get_field_mapping(
human: t.Optional[bool] = None,
ignore_unavailable: t.Optional[bool] = None,
include_defaults: t.Optional[bool] = None,
+ local: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
) -> ObjectApiResponse[t.Any]:
"""
@@ -2515,6 +2516,8 @@ def get_field_mapping(
:param ignore_unavailable: If `false`, the request returns an error if it targets
a missing or closed index.
:param include_defaults: If `true`, return all default settings in the response.
+ :param local: If `true`, the request retrieves information from the local node
+ only.
"""
if fields in SKIP_IN_PATH:
raise ValueError("Empty value passed for parameter 'fields'")
@@ -2542,6 +2545,8 @@ def get_field_mapping(
__query["ignore_unavailable"] = ignore_unavailable
if include_defaults is not None:
__query["include_defaults"] = include_defaults
+ if local is not None:
+ __query["local"] = local
if pretty is not None:
__query["pretty"] = pretty
__headers = {"accept": "application/json"}
@@ -2726,7 +2731,7 @@ def get_migrate_reindex_status(
Get the status of a migration reindex attempt for a data stream or index.
- ``_
+ ``_
:param index: The index or data stream name.
"""
@@ -2945,7 +2950,7 @@ def migrate_reindex(
The persistent task ID is returned immediately and the reindexing work is completed in that task.
- ``_
+ ``_
:param reindex:
"""
@@ -3006,7 +3011,7 @@ def migrate_to_data_stream(
The write index for the alias becomes the write index for the stream.
- ``_
+ ``_
:param name: Name of the index alias to convert to a data stream.
:param master_timeout: Period to wait for a connection to the master node. If
@@ -3062,7 +3067,7 @@ def modify_data_stream(
Performs one or more data stream modification actions in a single atomic operation.
- ``_
+ ``_
:param actions: Actions to perform.
"""
@@ -3227,7 +3232,7 @@ def promote_data_stream(
This will affect the lifecycle management of the data stream and interfere with the data stream size and retention.
- ``_
+ ``_
:param name: The name of the data stream
:param master_timeout: Period to wait for a connection to the master node. If
@@ -3293,7 +3298,7 @@ def put_alias(
Adds a data stream or index to an alias.
- ``_
+ ``_
:param index: Comma-separated list of data streams or indices to add. Supports
wildcards (`*`). Wildcard patterns that match both data streams and indices
@@ -3400,7 +3405,7 @@ def put_data_lifecycle(
Update the data stream lifecycle of the specified data streams.
- ``_
+ ``_
:param name: Comma-separated list of data streams used to limit the request.
Supports wildcards (`*`). To target all data streams use `*` or `_all`.
@@ -3528,7 +3533,7 @@ def put_index_template(
If an entry already exists with the same key, then it is overwritten by the new definition.
- ``_
+ ``_
:param name: Index or template name
:param allow_auto_create: This setting overrides the value of the `action.auto_create_index`
@@ -5372,7 +5377,7 @@ def update_aliases(
Adds a data stream or index to an alias.
- ``_
+ ``_
:param actions: Actions to perform.
:param master_timeout: Period to wait for a connection to the master node. If
@@ -5451,7 +5456,7 @@ def validate_query(
Validates a query without running it.
- ``_
+ ``_
:param index: Comma-separated list of data streams, indices, and aliases to search.
Supports wildcards (`*`). To search all data streams or indices, omit this
diff --git a/elasticsearch/_sync/client/inference.py b/elasticsearch/_sync/client/inference.py
index 911a8a530..2ae2b637d 100644
--- a/elasticsearch/_sync/client/inference.py
+++ b/elasticsearch/_sync/client/inference.py
@@ -25,6 +25,74 @@
class InferenceClient(NamespacedClient):
+ @_rewrite_parameters(
+ body_fields=("input", "task_settings"),
+ )
+ def completion(
+ self,
+ *,
+ inference_id: str,
+ input: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Any] = None,
+ timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Perform completion inference on the service
+
+
+ ``_
+
+ :param inference_id: The inference Id
+ :param input: Inference input. Either a string or an array of strings.
+ :param task_settings: Optional task settings
+ :param timeout: Specifies the amount of time to wait for the inference request
+ to complete.
+ """
+ if inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'inference_id'")
+ if input is None and body is None:
+ raise ValueError("Empty value passed for parameter 'input'")
+ __path_parts: t.Dict[str, str] = {"inference_id": _quote(inference_id)}
+ __path = f'/_inference/completion/{__path_parts["inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if timeout is not None:
+ __query["timeout"] = timeout
+ if not __body:
+ if input is not None:
+ __body["input"] = input
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "POST",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.completion",
+ path_parts=__path_parts,
+ )
+
@_rewrite_parameters()
def delete(
self,
@@ -33,7 +101,13 @@ def delete(
task_type: t.Optional[
t.Union[
str,
- t.Literal["completion", "rerank", "sparse_embedding", "text_embedding"],
+ t.Literal[
+ "chat_completion",
+ "completion",
+ "rerank",
+ "sparse_embedding",
+ "text_embedding",
+ ],
]
] = None,
dry_run: t.Optional[bool] = None,
@@ -102,7 +176,13 @@ def get(
task_type: t.Optional[
t.Union[
str,
- t.Literal["completion", "rerank", "sparse_embedding", "text_embedding"],
+ t.Literal[
+ "chat_completion",
+ "completion",
+ "rerank",
+ "sparse_embedding",
+ "text_embedding",
+ ],
]
] = None,
inference_id: t.Optional[str] = None,
@@ -155,24 +235,188 @@ def get(
)
@_rewrite_parameters(
- body_fields=("input", "query", "task_settings"),
+ body_name="inference_config",
)
- def inference(
+ def put(
self,
*,
inference_id: str,
- input: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ inference_config: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Mapping[str, t.Any]] = None,
task_type: t.Optional[
t.Union[
str,
- t.Literal["completion", "rerank", "sparse_embedding", "text_embedding"],
+ t.Literal[
+ "chat_completion",
+ "completion",
+ "rerank",
+ "sparse_embedding",
+ "text_embedding",
+ ],
]
] = None,
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an inference endpoint.
+ When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
IMPORTANT: The inference APIs enable you to use certain services, such as built-in machine learning models (ELSER, E5), models uploaded through Eland, Cohere, OpenAI, Mistral, Azure OpenAI, Google AI Studio, Google Vertex AI, Anthropic, Watsonx.ai, or Hugging Face.
+ For built-in models and models uploaded through Eland, the inference APIs offer an alternative way to use and manage trained models.
+ However, if you do not plan to use the inference APIs to use these models or if you want to use non-NLP models, use the machine learning trained model APIs.
+
+
+ ``_
+
+ :param inference_id: The inference Id
+ :param inference_config:
+ :param task_type: The task type
+ """
+ if inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'inference_id'")
+ if inference_config is None and body is None:
+ raise ValueError(
+ "Empty value passed for parameters 'inference_config' and 'body', one of them should be set."
+ )
+ elif inference_config is not None and body is not None:
+ raise ValueError("Cannot set both 'inference_config' and 'body'")
+ __path_parts: t.Dict[str, str]
+ if task_type not in SKIP_IN_PATH and inference_id not in SKIP_IN_PATH:
+ __path_parts = {
+ "task_type": _quote(task_type),
+ "inference_id": _quote(inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["inference_id"]}'
+ elif inference_id not in SKIP_IN_PATH:
+ __path_parts = {"inference_id": _quote(inference_id)}
+ __path = f'/_inference/{__path_parts["inference_id"]}'
+ else:
+ raise ValueError("Couldn't find a path for the given parameters")
+ __query: t.Dict[str, t.Any] = {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ __body = inference_config if inference_config is not None else body
+ __headers = {"accept": "application/json", "content-type": "application/json"}
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("service", "service_settings"),
+ )
+ def put_watsonx(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["text_embedding"]],
+ watsonx_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["watsonxai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create a Watsonx inference endpoint.
+
Creates an inference endpoint to perform an inference task with the watsonxai service.
+ You need an IBM Cloud Databases for Elasticsearch deployment to use the watsonxai inference service.
+ You can provision one through the IBM catalog, the Cloud Databases CLI plug-in, the Cloud Databases API, or Terraform.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The task type. The only valid task type for the model to perform
+ is `text_embedding`.
+ :param watsonx_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `watsonxai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `watsonxai` service.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if watsonx_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'watsonx_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "watsonx_inference_id": _quote(watsonx_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["watsonx_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_watsonx",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("input", "query", "task_settings"),
+ )
+ def rerank(
+ self,
+ *,
+ inference_id: str,
+ input: t.Optional[t.Union[str, t.Sequence[str]]] = None,
query: t.Optional[str] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
task_settings: t.Optional[t.Any] = None,
timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
body: t.Optional[t.Dict[str, t.Any]] = None,
@@ -180,14 +424,7 @@ def inference(
"""
.. raw:: html
-
Perform inference on the service.
-
This API enables you to use machine learning models to perform specific tasks on data that you provide as an input.
- It returns a response with the results of the tasks.
- The inference endpoint you use can perform one specific task that has been defined when the endpoint was created with the create inference API.
-
-
info
- The inference APIs enable you to use certain services, such as built-in machine learning models (ELSER, E5), models uploaded through Eland, Cohere, OpenAI, Azure, Google AI Studio, Google Vertex AI, Anthropic, Watsonx.ai, or Hugging Face. For built-in models and models uploaded through Eland, the inference APIs offer an alternative way to use and manage trained models. However, if you do not plan to use the inference APIs to use these models or if you want to use non-NLP models, use the machine learning trained model APIs.
-
+
Perform rereanking inference on the service
``_
@@ -196,9 +433,7 @@ def inference(
:param input: The text on which you want to perform the inference task. It can
be a single string or an array. > info > Inference endpoints for the `completion`
task type currently only support a single string as input.
- :param task_type: The type of inference task that the model performs.
- :param query: The query input, which is required only for the `rerank` task.
- It is not required for other tasks.
+ :param query: Query input.
:param task_settings: Task settings for the individual inference request. These
settings are specific to the task type you specified and override the task
settings specified when initializing the service.
@@ -208,18 +443,10 @@ def inference(
raise ValueError("Empty value passed for parameter 'inference_id'")
if input is None and body is None:
raise ValueError("Empty value passed for parameter 'input'")
- __path_parts: t.Dict[str, str]
- if task_type not in SKIP_IN_PATH and inference_id not in SKIP_IN_PATH:
- __path_parts = {
- "task_type": _quote(task_type),
- "inference_id": _quote(inference_id),
- }
- __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["inference_id"]}'
- elif inference_id not in SKIP_IN_PATH:
- __path_parts = {"inference_id": _quote(inference_id)}
- __path = f'/_inference/{__path_parts["inference_id"]}'
- else:
- raise ValueError("Couldn't find a path for the given parameters")
+ if query is None and body is None:
+ raise ValueError("Empty value passed for parameter 'query'")
+ __path_parts: t.Dict[str, str] = {"inference_id": _quote(inference_id)}
+ __path = f'/_inference/rerank/{__path_parts["inference_id"]}'
__query: t.Dict[str, t.Any] = {}
__body: t.Dict[str, t.Any] = body if body is not None else {}
if error_trace is not None:
@@ -250,71 +477,48 @@ def inference(
params=__query,
headers=__headers,
body=__body,
- endpoint_id="inference.inference",
+ endpoint_id="inference.rerank",
path_parts=__path_parts,
)
@_rewrite_parameters(
- body_name="inference_config",
+ body_fields=("input", "task_settings"),
)
- def put(
+ def sparse_embedding(
self,
*,
inference_id: str,
- inference_config: t.Optional[t.Mapping[str, t.Any]] = None,
- body: t.Optional[t.Mapping[str, t.Any]] = None,
- task_type: t.Optional[
- t.Union[
- str,
- t.Literal["completion", "rerank", "sparse_embedding", "text_embedding"],
- ]
- ] = None,
+ input: t.Optional[t.Union[str, t.Sequence[str]]] = None,
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Any] = None,
+ timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
) -> ObjectApiResponse[t.Any]:
"""
.. raw:: html
-
Create an inference endpoint.
- When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
- After creating the endpoint, wait for the model deployment to complete before using it.
- To verify the deployment status, use the get trained model statistics API.
- Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
- Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
-
IMPORTANT: The inference APIs enable you to use certain services, such as built-in machine learning models (ELSER, E5), models uploaded through Eland, Cohere, OpenAI, Mistral, Azure OpenAI, Google AI Studio, Google Vertex AI, Anthropic, Watsonx.ai, or Hugging Face.
- For built-in models and models uploaded through Eland, the inference APIs offer an alternative way to use and manage trained models.
- However, if you do not plan to use the inference APIs to use these models or if you want to use non-NLP models, use the machine learning trained model APIs.
+
Perform sparse embedding inference on the service
- ``_
+ ``_
:param inference_id: The inference Id
- :param inference_config:
- :param task_type: The task type
+ :param input: Inference input. Either a string or an array of strings.
+ :param task_settings: Optional task settings
+ :param timeout: Specifies the amount of time to wait for the inference request
+ to complete.
"""
if inference_id in SKIP_IN_PATH:
raise ValueError("Empty value passed for parameter 'inference_id'")
- if inference_config is None and body is None:
- raise ValueError(
- "Empty value passed for parameters 'inference_config' and 'body', one of them should be set."
- )
- elif inference_config is not None and body is not None:
- raise ValueError("Cannot set both 'inference_config' and 'body'")
- __path_parts: t.Dict[str, str]
- if task_type not in SKIP_IN_PATH and inference_id not in SKIP_IN_PATH:
- __path_parts = {
- "task_type": _quote(task_type),
- "inference_id": _quote(inference_id),
- }
- __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["inference_id"]}'
- elif inference_id not in SKIP_IN_PATH:
- __path_parts = {"inference_id": _quote(inference_id)}
- __path = f'/_inference/{__path_parts["inference_id"]}'
- else:
- raise ValueError("Couldn't find a path for the given parameters")
+ if input is None and body is None:
+ raise ValueError("Empty value passed for parameter 'input'")
+ __path_parts: t.Dict[str, str] = {"inference_id": _quote(inference_id)}
+ __path = f'/_inference/sparse_embedding/{__path_parts["inference_id"]}'
__query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
if error_trace is not None:
__query["error_trace"] = error_trace
if filter_path is not None:
@@ -323,15 +527,93 @@ def put(
__query["human"] = human
if pretty is not None:
__query["pretty"] = pretty
- __body = inference_config if inference_config is not None else body
- __headers = {"accept": "application/json", "content-type": "application/json"}
+ if timeout is not None:
+ __query["timeout"] = timeout
+ if not __body:
+ if input is not None:
+ __body["input"] = input
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
return self.perform_request( # type: ignore[return-value]
- "PUT",
+ "POST",
__path,
params=__query,
headers=__headers,
body=__body,
- endpoint_id="inference.put",
+ endpoint_id="inference.sparse_embedding",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("input", "task_settings"),
+ )
+ def text_embedding(
+ self,
+ *,
+ inference_id: str,
+ input: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Any] = None,
+ timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Perform text embedding inference on the service
+
+
+ ``_
+
+ :param inference_id: The inference Id
+ :param input: Inference input. Either a string or an array of strings.
+ :param task_settings: Optional task settings
+ :param timeout: Specifies the amount of time to wait for the inference request
+ to complete.
+ """
+ if inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'inference_id'")
+ if input is None and body is None:
+ raise ValueError("Empty value passed for parameter 'input'")
+ __path_parts: t.Dict[str, str] = {"inference_id": _quote(inference_id)}
+ __path = f'/_inference/text_embedding/{__path_parts["inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if timeout is not None:
+ __query["timeout"] = timeout
+ if not __body:
+ if input is not None:
+ __body["input"] = input
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "POST",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.text_embedding",
path_parts=__path_parts,
)
@@ -347,7 +629,13 @@ def update(
task_type: t.Optional[
t.Union[
str,
- t.Literal["completion", "rerank", "sparse_embedding", "text_embedding"],
+ t.Literal[
+ "chat_completion",
+ "completion",
+ "rerank",
+ "sparse_embedding",
+ "text_embedding",
+ ],
]
] = None,
error_trace: t.Optional[bool] = None,
@@ -403,7 +691,7 @@ def update(
__body = inference_config if inference_config is not None else body
__headers = {"accept": "application/json", "content-type": "application/json"}
return self.perform_request( # type: ignore[return-value]
- "POST",
+ "PUT",
__path,
params=__query,
headers=__headers,
diff --git a/elasticsearch/_sync/client/ingest.py b/elasticsearch/_sync/client/ingest.py
index 2a1b0463d..3a66284e9 100644
--- a/elasticsearch/_sync/client/ingest.py
+++ b/elasticsearch/_sync/client/ingest.py
@@ -208,7 +208,7 @@ def geo_ip_stats(
Get download statistics for GeoIP2 databases that are used with the GeoIP processor.
- ``_
+ ``_
"""
__path_parts: t.Dict[str, str] = {}
__path = "/_ingest/geoip/stats"
@@ -412,7 +412,7 @@ def processor_grok(
A grok pattern is like a regular expression that supports aliased expressions that can be reused.
- ``_
+ ``_
"""
__path_parts: t.Dict[str, str] = {}
__path = "/_ingest/processor/grok"
@@ -620,7 +620,7 @@ def put_pipeline(
Changes made using this API take effect immediately.
- ``_
+ ``_
:param id: ID of the ingest pipeline to create or update.
:param deprecated: Marks this ingest pipeline as deprecated. When a deprecated
diff --git a/elasticsearch/_sync/client/ml.py b/elasticsearch/_sync/client/ml.py
index 32c00028f..3713ff741 100644
--- a/elasticsearch/_sync/client/ml.py
+++ b/elasticsearch/_sync/client/ml.py
@@ -2616,7 +2616,6 @@ def get_trained_models(
],
]
] = None,
- include_model_definition: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
size: t.Optional[int] = None,
tags: t.Optional[t.Union[str, t.Sequence[str]]] = None,
@@ -2646,8 +2645,6 @@ def get_trained_models(
:param from_: Skips the specified number of models.
:param include: A comma delimited string of optional fields to include in the
response body.
- :param include_model_definition: parameter is deprecated! Use [include=definition]
- instead
:param size: Specifies the maximum number of models to obtain.
:param tags: A comma delimited string of tags. A trained model can have many
tags, or none. When supplied, only trained models that contain all the supplied
@@ -2677,8 +2674,6 @@ def get_trained_models(
__query["human"] = human
if include is not None:
__query["include"] = include
- if include_model_definition is not None:
- __query["include_model_definition"] = include_model_definition
if pretty is not None:
__query["pretty"] = pretty
if size is not None:
@@ -5733,7 +5728,7 @@ def validate(
Validate an anomaly detection job.
- ``_
+ ``_
:param analysis_config:
:param analysis_limits:
diff --git a/elasticsearch/_sync/client/simulate.py b/elasticsearch/_sync/client/simulate.py
index ed5442d97..5f22ae433 100644
--- a/elasticsearch/_sync/client/simulate.py
+++ b/elasticsearch/_sync/client/simulate.py
@@ -35,7 +35,7 @@ class SimulateClient(NamespacedClient):
body_fields=(
"docs",
"component_template_substitutions",
- "index_template_subtitutions",
+ "index_template_substitutions",
"mapping_addition",
"pipeline_substitutions",
),
@@ -52,7 +52,7 @@ def ingest(
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
- index_template_subtitutions: t.Optional[
+ index_template_substitutions: t.Optional[
t.Mapping[str, t.Mapping[str, t.Any]]
] = None,
mapping_addition: t.Optional[t.Mapping[str, t.Any]] = None,
@@ -90,7 +90,7 @@ def ingest(
an index argument.
:param component_template_substitutions: A map of component template names to
substitute component template definition objects.
- :param index_template_subtitutions: A map of index template names to substitute
+ :param index_template_substitutions: A map of index template names to substitute
index template definition objects.
:param mapping_addition:
:param pipeline: The pipeline to use as the default pipeline. This value can
@@ -127,8 +127,8 @@ def ingest(
__body["component_template_substitutions"] = (
component_template_substitutions
)
- if index_template_subtitutions is not None:
- __body["index_template_subtitutions"] = index_template_subtitutions
+ if index_template_substitutions is not None:
+ __body["index_template_substitutions"] = index_template_substitutions
if mapping_addition is not None:
__body["mapping_addition"] = mapping_addition
if pipeline_substitutions is not None:
diff --git a/elasticsearch/dsl/query.py b/elasticsearch/dsl/query.py
index b5808959c..6e87f926c 100644
--- a/elasticsearch/dsl/query.py
+++ b/elasticsearch/dsl/query.py
@@ -795,6 +795,28 @@ def __init__(
)
+class GeoGrid(Query):
+ """
+ Matches `geo_point` and `geo_shape` values that intersect a grid cell
+ from a GeoGrid aggregation.
+
+ :arg _field: The field to use in this query.
+ :arg _value: The query value for the field.
+ """
+
+ name = "geo_grid"
+
+ def __init__(
+ self,
+ _field: Union[str, "InstrumentedField", "DefaultType"] = DEFAULT,
+ _value: Union["types.GeoGridQuery", Dict[str, Any], "DefaultType"] = DEFAULT,
+ **kwargs: Any,
+ ):
+ if _field is not DEFAULT:
+ kwargs[str(_field)] = _value
+ super().__init__(**kwargs)
+
+
class GeoPolygon(Query):
"""
:arg _field: The field to use in this query.
diff --git a/elasticsearch/dsl/types.py b/elasticsearch/dsl/types.py
index d1c39003e..4ea6d8361 100644
--- a/elasticsearch/dsl/types.py
+++ b/elasticsearch/dsl/types.py
@@ -880,6 +880,48 @@ def __init__(
super().__init__(kwargs)
+class GeoGridQuery(AttrDict[Any]):
+ """
+ :arg geogrid:
+ :arg geohash:
+ :arg geohex:
+ :arg boost: Floating point number used to decrease or increase the
+ relevance scores of the query. Boost values are relative to the
+ default value of 1.0. A boost value between 0 and 1.0 decreases
+ the relevance score. A value greater than 1.0 increases the
+ relevance score. Defaults to `1` if omitted.
+ :arg _name:
+ """
+
+ geogrid: Union[str, DefaultType]
+ geohash: Union[str, DefaultType]
+ geohex: Union[str, DefaultType]
+ boost: Union[float, DefaultType]
+ _name: Union[str, DefaultType]
+
+ def __init__(
+ self,
+ *,
+ geogrid: Union[str, DefaultType] = DEFAULT,
+ geohash: Union[str, DefaultType] = DEFAULT,
+ geohex: Union[str, DefaultType] = DEFAULT,
+ boost: Union[float, DefaultType] = DEFAULT,
+ _name: Union[str, DefaultType] = DEFAULT,
+ **kwargs: Any,
+ ):
+ if geogrid is not DEFAULT:
+ kwargs["geogrid"] = geogrid
+ if geohash is not DEFAULT:
+ kwargs["geohash"] = geohash
+ if geohex is not DEFAULT:
+ kwargs["geohex"] = geohex
+ if boost is not DEFAULT:
+ kwargs["boost"] = boost
+ if _name is not DEFAULT:
+ kwargs["_name"] = _name
+ super().__init__(kwargs)
+
+
class GeoHashLocation(AttrDict[Any]):
"""
:arg geohash: (required)
From a35da3c566ffd025ee8bc75bc778a86caa34c3d9 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 19 Mar 2025 10:38:31 +0000
Subject: [PATCH 05/57] rename DSL documentation for clarity (#2851) (#2852)
(cherry picked from commit 4ef7740a977aa3d7b202c3c7c4bec2cd24d7106f)
Co-authored-by: Miguel Grinberg
---
.../{_configuration.md => dsl_configuration.md} | 0
docs/reference/{_examples.md => dsl_examples.md} | 0
.../{_how_to_guides.md => dsl_how_to_guides.md} | 0
docs/reference/{_tutorials.md => dsl_tutorials.md} | 0
docs/reference/toc.yml | 10 +++++-----
5 files changed, 5 insertions(+), 5 deletions(-)
rename docs/reference/{_configuration.md => dsl_configuration.md} (100%)
rename docs/reference/{_examples.md => dsl_examples.md} (100%)
rename docs/reference/{_how_to_guides.md => dsl_how_to_guides.md} (100%)
rename docs/reference/{_tutorials.md => dsl_tutorials.md} (100%)
diff --git a/docs/reference/_configuration.md b/docs/reference/dsl_configuration.md
similarity index 100%
rename from docs/reference/_configuration.md
rename to docs/reference/dsl_configuration.md
diff --git a/docs/reference/_examples.md b/docs/reference/dsl_examples.md
similarity index 100%
rename from docs/reference/_examples.md
rename to docs/reference/dsl_examples.md
diff --git a/docs/reference/_how_to_guides.md b/docs/reference/dsl_how_to_guides.md
similarity index 100%
rename from docs/reference/_how_to_guides.md
rename to docs/reference/dsl_how_to_guides.md
diff --git a/docs/reference/_tutorials.md b/docs/reference/dsl_tutorials.md
similarity index 100%
rename from docs/reference/_tutorials.md
rename to docs/reference/dsl_tutorials.md
diff --git a/docs/reference/toc.yml b/docs/reference/toc.yml
index 8de284050..abb74bc42 100644
--- a/docs/reference/toc.yml
+++ b/docs/reference/toc.yml
@@ -12,8 +12,8 @@ toc:
- file: examples.md
- file: elasticsearch-dsl.md
children:
- - file: _configuration.md
- - file: _tutorials.md
- - file: _how_to_guides.md
- - file: _examples.md
- - file: client-helpers.md
\ No newline at end of file
+ - file: dsl_configuration.md
+ - file: dsl_tutorials.md
+ - file: dsl_how_to_guides.md
+ - file: dsl_examples.md
+ - file: client-helpers.md
From c31463e456b87a302d6fcbcff40f37c78b536655 Mon Sep 17 00:00:00 2001
From: Elastic Machine
Date: Mon, 24 Mar 2025 10:04:51 +0200
Subject: [PATCH 06/57] Auto-generated API code (#2848)
---
elasticsearch/_async/client/__init__.py | 85 ++++++++++++++-----
elasticsearch/_async/client/esql.py | 5 +-
elasticsearch/_async/client/indices.py | 51 ++++++++++--
elasticsearch/_async/client/inference.py | 102 ++++++++++++++++++++++-
elasticsearch/_async/client/ml.py | 8 +-
elasticsearch/_async/client/security.py | 14 ++--
elasticsearch/_sync/client/__init__.py | 85 ++++++++++++++-----
elasticsearch/_sync/client/esql.py | 5 +-
elasticsearch/_sync/client/indices.py | 51 ++++++++++--
elasticsearch/_sync/client/inference.py | 102 ++++++++++++++++++++++-
elasticsearch/_sync/client/ml.py | 8 +-
elasticsearch/_sync/client/security.py | 14 ++--
elasticsearch/dsl/field.py | 68 +++++++++++----
elasticsearch/dsl/types.py | 55 ++++++++----
14 files changed, 530 insertions(+), 123 deletions(-)
diff --git a/elasticsearch/_async/client/__init__.py b/elasticsearch/_async/client/__init__.py
index b0992bd67..a897f2d37 100644
--- a/elasticsearch/_async/client/__init__.py
+++ b/elasticsearch/_async/client/__init__.py
@@ -1121,12 +1121,17 @@ async def create(
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
+ if_primary_term: t.Optional[int] = None,
+ if_seq_no: t.Optional[int] = None,
include_source_on_error: t.Optional[bool] = None,
+ op_type: t.Optional[t.Union[str, t.Literal["create", "index"]]] = None,
pipeline: t.Optional[str] = None,
pretty: t.Optional[bool] = None,
refresh: t.Optional[
t.Union[bool, str, t.Literal["false", "true", "wait_for"]]
] = None,
+ require_alias: t.Optional[bool] = None,
+ require_data_stream: t.Optional[bool] = None,
routing: t.Optional[str] = None,
timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
version: t.Optional[int] = None,
@@ -1204,8 +1209,18 @@ async def create(
:param id: A unique identifier for the document. To automatically generate a
document ID, use the `POST //_doc/` request format.
:param document:
+ :param if_primary_term: Only perform the operation if the document has this primary
+ term.
+ :param if_seq_no: Only perform the operation if the document has this sequence
+ number.
:param include_source_on_error: True or false if to include the document source
in the error message in case of parsing errors.
+ :param op_type: Set to `create` to only index the document if it does not already
+ exist (put if absent). If a document with the specified `_id` already exists,
+ the indexing operation will fail. The behavior is the same as using the `/_create`
+ endpoint. If a document ID is specified, this paramater defaults to `index`.
+ Otherwise, it defaults to `create`. If the request targets a data stream,
+ an `op_type` of `create` is required.
:param pipeline: The ID of the pipeline to use to preprocess incoming documents.
If the index has a default ingest pipeline specified, setting the value to
`_none` turns off the default ingest pipeline for this request. If a final
@@ -1214,6 +1229,9 @@ async def create(
:param refresh: If `true`, Elasticsearch refreshes the affected shards to make
this operation visible to search. If `wait_for`, it waits for a refresh to
make this operation visible to search. If `false`, it does nothing with refreshes.
+ :param require_alias: If `true`, the destination must be an index alias.
+ :param require_data_stream: If `true`, the request's actions must target a data
+ stream (existing or to be created).
:param routing: A custom value that is used to route operations to a specific
shard.
:param timeout: The period the request waits for the following operations: automatic
@@ -1254,14 +1272,24 @@ async def create(
__query["filter_path"] = filter_path
if human is not None:
__query["human"] = human
+ if if_primary_term is not None:
+ __query["if_primary_term"] = if_primary_term
+ if if_seq_no is not None:
+ __query["if_seq_no"] = if_seq_no
if include_source_on_error is not None:
__query["include_source_on_error"] = include_source_on_error
+ if op_type is not None:
+ __query["op_type"] = op_type
if pipeline is not None:
__query["pipeline"] = pipeline
if pretty is not None:
__query["pretty"] = pretty
if refresh is not None:
__query["refresh"] = refresh
+ if require_alias is not None:
+ __query["require_alias"] = require_alias
+ if require_data_stream is not None:
+ __query["require_data_stream"] = require_data_stream
if routing is not None:
__query["routing"] = routing
if timeout is not None:
@@ -5969,7 +5997,20 @@ async def terms_enum(
)
@_rewrite_parameters(
- body_fields=("doc", "filter", "per_field_analyzer"),
+ body_fields=(
+ "doc",
+ "field_statistics",
+ "fields",
+ "filter",
+ "offsets",
+ "payloads",
+ "per_field_analyzer",
+ "positions",
+ "routing",
+ "term_statistics",
+ "version",
+ "version_type",
+ ),
)
async def termvectors(
self,
@@ -6046,9 +6087,9 @@ async def termvectors(
(the sum of document frequencies for all terms in this field). * The sum
of total term frequencies (the sum of total term frequencies of each term
in this field).
- :param fields: A comma-separated list or wildcard expressions of fields to include
- in the statistics. It is used as the default list unless a specific field
- list is provided in the `completion_fields` or `fielddata_fields` parameters.
+ :param fields: A list of fields to include in the statistics. It is used as the
+ default list unless a specific field list is provided in the `completion_fields`
+ or `fielddata_fields` parameters.
:param filter: Filter terms based on their tf-idf scores. This could be useful
in order find out a good characteristic vector of a document. This feature
works in a similar manner to the second phase of the More Like This Query.
@@ -6086,41 +6127,41 @@ async def termvectors(
__body: t.Dict[str, t.Any] = body if body is not None else {}
if error_trace is not None:
__query["error_trace"] = error_trace
- if field_statistics is not None:
- __query["field_statistics"] = field_statistics
- if fields is not None:
- __query["fields"] = fields
if filter_path is not None:
__query["filter_path"] = filter_path
if human is not None:
__query["human"] = human
- if offsets is not None:
- __query["offsets"] = offsets
- if payloads is not None:
- __query["payloads"] = payloads
- if positions is not None:
- __query["positions"] = positions
if preference is not None:
__query["preference"] = preference
if pretty is not None:
__query["pretty"] = pretty
if realtime is not None:
__query["realtime"] = realtime
- if routing is not None:
- __query["routing"] = routing
- if term_statistics is not None:
- __query["term_statistics"] = term_statistics
- if version is not None:
- __query["version"] = version
- if version_type is not None:
- __query["version_type"] = version_type
if not __body:
if doc is not None:
__body["doc"] = doc
+ if field_statistics is not None:
+ __body["field_statistics"] = field_statistics
+ if fields is not None:
+ __body["fields"] = fields
if filter is not None:
__body["filter"] = filter
+ if offsets is not None:
+ __body["offsets"] = offsets
+ if payloads is not None:
+ __body["payloads"] = payloads
if per_field_analyzer is not None:
__body["per_field_analyzer"] = per_field_analyzer
+ if positions is not None:
+ __body["positions"] = positions
+ if routing is not None:
+ __body["routing"] = routing
+ if term_statistics is not None:
+ __body["term_statistics"] = term_statistics
+ if version is not None:
+ __body["version"] = version
+ if version_type is not None:
+ __body["version_type"] = version_type
if not __body:
__body = None # type: ignore[assignment]
__headers = {"accept": "application/json"}
diff --git a/elasticsearch/_async/client/esql.py b/elasticsearch/_async/client/esql.py
index dca7ca2bb..d1a83e00b 100644
--- a/elasticsearch/_async/client/esql.py
+++ b/elasticsearch/_async/client/esql.py
@@ -35,6 +35,7 @@ class EsqlClient(NamespacedClient):
"params",
"profile",
"tables",
+ "wait_for_completion_timeout",
),
ignore_deprecated_options={"params"},
)
@@ -150,8 +151,6 @@ async def async_query(
__query["keep_on_completion"] = keep_on_completion
if pretty is not None:
__query["pretty"] = pretty
- if wait_for_completion_timeout is not None:
- __query["wait_for_completion_timeout"] = wait_for_completion_timeout
if not __body:
if query is not None:
__body["query"] = query
@@ -169,6 +168,8 @@ async def async_query(
__body["profile"] = profile
if tables is not None:
__body["tables"] = tables
+ if wait_for_completion_timeout is not None:
+ __body["wait_for_completion_timeout"] = wait_for_completion_timeout
__headers = {"accept": "application/json", "content-type": "application/json"}
return await self.perform_request( # type: ignore[return-value]
"POST",
diff --git a/elasticsearch/_async/client/indices.py b/elasticsearch/_async/client/indices.py
index ac3f93d8f..0c128e9d9 100644
--- a/elasticsearch/_async/client/indices.py
+++ b/elasticsearch/_async/client/indices.py
@@ -1622,7 +1622,9 @@ async def exists_index_template(
name: str,
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ flat_settings: t.Optional[bool] = None,
human: t.Optional[bool] = None,
+ local: t.Optional[bool] = None,
master_timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
pretty: t.Optional[bool] = None,
) -> HeadApiResponse:
@@ -1637,6 +1639,10 @@ async def exists_index_template(
:param name: Comma-separated list of index template names used to limit the request.
Wildcard (*) expressions are supported.
+ :param flat_settings: If true, returns settings in flat format.
+ :param local: If true, the request retrieves information from the local node
+ only. Defaults to false, which means information is retrieved from the master
+ node.
:param master_timeout: Period to wait for a connection to the master node. If
no response is received before the timeout expires, the request fails and
returns an error.
@@ -1650,8 +1656,12 @@ async def exists_index_template(
__query["error_trace"] = error_trace
if filter_path is not None:
__query["filter_path"] = filter_path
+ if flat_settings is not None:
+ __query["flat_settings"] = flat_settings
if human is not None:
__query["human"] = human
+ if local is not None:
+ __query["local"] = local
if master_timeout is not None:
__query["master_timeout"] = master_timeout
if pretty is not None:
@@ -1801,9 +1811,6 @@ async def field_usage_stats(
human: t.Optional[bool] = None,
ignore_unavailable: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
- wait_for_active_shards: t.Optional[
- t.Union[int, t.Union[str, t.Literal["all", "index-setting"]]]
- ] = None,
) -> ObjectApiResponse[t.Any]:
"""
.. raw:: html
@@ -1833,9 +1840,6 @@ async def field_usage_stats(
in the statistics.
:param ignore_unavailable: If `true`, missing or closed indices are not included
in the response.
- :param wait_for_active_shards: The number of shard copies that must be active
- before proceeding with the operation. Set to all or any positive integer
- up to the total number of shards in the index (`number_of_replicas+1`).
"""
if index in SKIP_IN_PATH:
raise ValueError("Empty value passed for parameter 'index'")
@@ -1858,8 +1862,6 @@ async def field_usage_stats(
__query["ignore_unavailable"] = ignore_unavailable
if pretty is not None:
__query["pretty"] = pretty
- if wait_for_active_shards is not None:
- __query["wait_for_active_shards"] = wait_for_active_shards
__headers = {"accept": "application/json"}
return await self.perform_request( # type: ignore[return-value]
"GET",
@@ -3840,6 +3842,7 @@ async def put_settings(
master_timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
preserve_existing: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
+ reopen: t.Optional[bool] = None,
timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
) -> ObjectApiResponse[t.Any]:
"""
@@ -3882,6 +3885,9 @@ async def put_settings(
no response is received before the timeout expires, the request fails and
returns an error.
:param preserve_existing: If `true`, existing index settings remain unchanged.
+ :param reopen: Whether to close and reopen the index to apply non-dynamic settings.
+ If set to `true` the indices to which the settings are being applied will
+ be closed temporarily and then reopened in order to apply the changes.
:param timeout: Period to wait for a response. If no response is received before
the timeout expires, the request fails and returns an error.
"""
@@ -3919,6 +3925,8 @@ async def put_settings(
__query["preserve_existing"] = preserve_existing
if pretty is not None:
__query["pretty"] = pretty
+ if reopen is not None:
+ __query["reopen"] = reopen
if timeout is not None:
__query["timeout"] = timeout
__body = settings if settings is not None else body
@@ -3986,7 +3994,7 @@ async def put_template(
:param name: The name of the template
:param aliases: Aliases for the index.
- :param cause:
+ :param cause: User defined reason for creating/updating the index template
:param create: If true, this request cannot replace or update existing index
templates.
:param index_patterns: Array of wildcard expressions used to match the names
@@ -4224,6 +4232,7 @@ async def reload_search_analyzers(
human: t.Optional[bool] = None,
ignore_unavailable: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
+ resource: t.Optional[str] = None,
) -> ObjectApiResponse[t.Any]:
"""
.. raw:: html
@@ -4251,6 +4260,7 @@ async def reload_search_analyzers(
that are open, closed or both.
:param ignore_unavailable: Whether specified concrete indices should be ignored
when unavailable (missing or closed)
+ :param resource: Changed resource to reload analyzers from if applicable
"""
if index in SKIP_IN_PATH:
raise ValueError("Empty value passed for parameter 'index'")
@@ -4271,6 +4281,8 @@ async def reload_search_analyzers(
__query["ignore_unavailable"] = ignore_unavailable
if pretty is not None:
__query["pretty"] = pretty
+ if resource is not None:
+ __query["resource"] = resource
__headers = {"accept": "application/json"}
return await self.perform_request( # type: ignore[return-value]
"POST",
@@ -4507,6 +4519,7 @@ async def rollover(
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
+ lazy: t.Optional[bool] = None,
mappings: t.Optional[t.Mapping[str, t.Any]] = None,
master_timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
pretty: t.Optional[bool] = None,
@@ -4563,6 +4576,9 @@ async def rollover(
conditions are satisfied.
:param dry_run: If `true`, checks whether the current index satisfies the specified
conditions but does not perform a rollover.
+ :param lazy: If set to true, the rollover action will only mark a data stream
+ to signal that it needs to be rolled over at the next write. Only allowed
+ on data streams.
:param mappings: Mapping for fields in the index. If specified, this mapping
can include field names, field data types, and mapping paramaters.
:param master_timeout: Period to wait for a connection to the master node. If
@@ -4597,6 +4613,8 @@ async def rollover(
__query["filter_path"] = filter_path
if human is not None:
__query["human"] = human
+ if lazy is not None:
+ __query["lazy"] = lazy
if master_timeout is not None:
__query["master_timeout"] = master_timeout
if pretty is not None:
@@ -4913,6 +4931,8 @@ async def simulate_index_template(
self,
*,
name: str,
+ cause: t.Optional[str] = None,
+ create: t.Optional[bool] = None,
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
@@ -4930,6 +4950,10 @@ async def simulate_index_template(
``_
:param name: Name of the index to simulate
+ :param cause: User defined reason for dry-run creating the new template for simulation
+ purposes
+ :param create: Whether the index template we optionally defined in the body should
+ only be dry-run added if new or can also replace an existing one
:param include_defaults: If true, returns all relevant default configurations
for the index template.
:param master_timeout: Period to wait for a connection to the master node. If
@@ -4941,6 +4965,10 @@ async def simulate_index_template(
__path_parts: t.Dict[str, str] = {"name": _quote(name)}
__path = f'/_index_template/_simulate_index/{__path_parts["name"]}'
__query: t.Dict[str, t.Any] = {}
+ if cause is not None:
+ __query["cause"] = cause
+ if create is not None:
+ __query["create"] = create
if error_trace is not None:
__query["error_trace"] = error_trace
if filter_path is not None:
@@ -4983,6 +5011,7 @@ async def simulate_template(
*,
name: t.Optional[str] = None,
allow_auto_create: t.Optional[bool] = None,
+ cause: t.Optional[str] = None,
composed_of: t.Optional[t.Sequence[str]] = None,
create: t.Optional[bool] = None,
data_stream: t.Optional[t.Mapping[str, t.Any]] = None,
@@ -5019,6 +5048,8 @@ async def simulate_template(
via `actions.auto_create_index`. If set to `false`, then indices or data
streams matching the template must always be explicitly created, and may
never be automatically created.
+ :param cause: User defined reason for dry-run creating the new template for simulation
+ purposes
:param composed_of: An ordered list of component template names. Component templates
are merged in the order specified, meaning that the last component template
specified has the highest precedence.
@@ -5063,6 +5094,8 @@ async def simulate_template(
__path = "/_index_template/_simulate"
__query: t.Dict[str, t.Any] = {}
__body: t.Dict[str, t.Any] = body if body is not None else {}
+ if cause is not None:
+ __query["cause"] = cause
if create is not None:
__query["create"] = create
if error_trace is not None:
diff --git a/elasticsearch/_async/client/inference.py b/elasticsearch/_async/client/inference.py
index e685d1c5c..ce96dba63 100644
--- a/elasticsearch/_async/client/inference.py
+++ b/elasticsearch/_async/client/inference.py
@@ -321,6 +321,104 @@ async def put(
path_parts=__path_parts,
)
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ async def put_openai(
+ self,
+ *,
+ task_type: t.Union[
+ str, t.Literal["chat_completion", "completion", "text_embedding"]
+ ],
+ openai_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["openai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an OpenAI inference endpoint.
+
Create an inference endpoint to perform an inference task with the openai service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ NOTE: The `chat_completion` task type only supports streaming and only through
+ the _stream API.
+ :param openai_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `openai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `openai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if openai_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'openai_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "openai_inference_id": _quote(openai_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["openai_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_openai",
+ path_parts=__path_parts,
+ )
+
@_rewrite_parameters(
body_fields=("service", "service_settings"),
)
@@ -341,7 +439,7 @@ async def put_watsonx(
.. raw:: html
Create a Watsonx inference endpoint.
-
Creates an inference endpoint to perform an inference task with the watsonxai service.
+
Create an inference endpoint to perform an inference task with the watsonxai service.
You need an IBM Cloud Databases for Elasticsearch deployment to use the watsonxai inference service.
You can provision one through the IBM catalog, the Cloud Databases CLI plug-in, the Cloud Databases API, or Terraform.
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
@@ -351,7 +449,7 @@ async def put_watsonx(
Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
- ``_
+ ``_
:param task_type: The task type. The only valid task type for the model to perform
is `text_embedding`.
diff --git a/elasticsearch/_async/client/ml.py b/elasticsearch/_async/client/ml.py
index 6599c0923..acee1e6ea 100644
--- a/elasticsearch/_async/client/ml.py
+++ b/elasticsearch/_async/client/ml.py
@@ -3599,11 +3599,11 @@ async def put_datafeed(
:param ignore_unavailable: If true, unavailable indices (missing or closed) are
ignored.
:param indexes: An array of index names. Wildcards are supported. If any of the
- indices are in remote clusters, the machine learning nodes must have the
- `remote_cluster_client` role.
+ indices are in remote clusters, the master nodes and the machine learning
+ nodes must have the `remote_cluster_client` role.
:param indices: An array of index names. Wildcards are supported. If any of the
- indices are in remote clusters, the machine learning nodes must have the
- `remote_cluster_client` role.
+ indices are in remote clusters, the master nodes and the machine learning
+ nodes must have the `remote_cluster_client` role.
:param indices_options: Specifies index expansion options that are used during
search
:param job_id: Identifier for the anomaly detection job.
diff --git a/elasticsearch/_async/client/security.py b/elasticsearch/_async/client/security.py
index 0bc3084a3..840a3d249 100644
--- a/elasticsearch/_async/client/security.py
+++ b/elasticsearch/_async/client/security.py
@@ -2867,12 +2867,12 @@ async def oidc_authenticate(
)
@_rewrite_parameters(
- body_fields=("access_token", "refresh_token"),
+ body_fields=("token", "refresh_token"),
)
async def oidc_logout(
self,
*,
- access_token: t.Optional[str] = None,
+ token: t.Optional[str] = None,
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
@@ -2892,11 +2892,11 @@ async def oidc_logout(
``_
- :param access_token: The access token to be invalidated.
+ :param token: The access token to be invalidated.
:param refresh_token: The refresh token to be invalidated.
"""
- if access_token is None and body is None:
- raise ValueError("Empty value passed for parameter 'access_token'")
+ if token is None and body is None:
+ raise ValueError("Empty value passed for parameter 'token'")
__path_parts: t.Dict[str, str] = {}
__path = "/_security/oidc/logout"
__query: t.Dict[str, t.Any] = {}
@@ -2910,8 +2910,8 @@ async def oidc_logout(
if pretty is not None:
__query["pretty"] = pretty
if not __body:
- if access_token is not None:
- __body["access_token"] = access_token
+ if token is not None:
+ __body["token"] = token
if refresh_token is not None:
__body["refresh_token"] = refresh_token
__headers = {"accept": "application/json", "content-type": "application/json"}
diff --git a/elasticsearch/_sync/client/__init__.py b/elasticsearch/_sync/client/__init__.py
index 32d736192..1d80efee7 100644
--- a/elasticsearch/_sync/client/__init__.py
+++ b/elasticsearch/_sync/client/__init__.py
@@ -1119,12 +1119,17 @@ def create(
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
+ if_primary_term: t.Optional[int] = None,
+ if_seq_no: t.Optional[int] = None,
include_source_on_error: t.Optional[bool] = None,
+ op_type: t.Optional[t.Union[str, t.Literal["create", "index"]]] = None,
pipeline: t.Optional[str] = None,
pretty: t.Optional[bool] = None,
refresh: t.Optional[
t.Union[bool, str, t.Literal["false", "true", "wait_for"]]
] = None,
+ require_alias: t.Optional[bool] = None,
+ require_data_stream: t.Optional[bool] = None,
routing: t.Optional[str] = None,
timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
version: t.Optional[int] = None,
@@ -1202,8 +1207,18 @@ def create(
:param id: A unique identifier for the document. To automatically generate a
document ID, use the `POST //_doc/` request format.
:param document:
+ :param if_primary_term: Only perform the operation if the document has this primary
+ term.
+ :param if_seq_no: Only perform the operation if the document has this sequence
+ number.
:param include_source_on_error: True or false if to include the document source
in the error message in case of parsing errors.
+ :param op_type: Set to `create` to only index the document if it does not already
+ exist (put if absent). If a document with the specified `_id` already exists,
+ the indexing operation will fail. The behavior is the same as using the `/_create`
+ endpoint. If a document ID is specified, this paramater defaults to `index`.
+ Otherwise, it defaults to `create`. If the request targets a data stream,
+ an `op_type` of `create` is required.
:param pipeline: The ID of the pipeline to use to preprocess incoming documents.
If the index has a default ingest pipeline specified, setting the value to
`_none` turns off the default ingest pipeline for this request. If a final
@@ -1212,6 +1227,9 @@ def create(
:param refresh: If `true`, Elasticsearch refreshes the affected shards to make
this operation visible to search. If `wait_for`, it waits for a refresh to
make this operation visible to search. If `false`, it does nothing with refreshes.
+ :param require_alias: If `true`, the destination must be an index alias.
+ :param require_data_stream: If `true`, the request's actions must target a data
+ stream (existing or to be created).
:param routing: A custom value that is used to route operations to a specific
shard.
:param timeout: The period the request waits for the following operations: automatic
@@ -1252,14 +1270,24 @@ def create(
__query["filter_path"] = filter_path
if human is not None:
__query["human"] = human
+ if if_primary_term is not None:
+ __query["if_primary_term"] = if_primary_term
+ if if_seq_no is not None:
+ __query["if_seq_no"] = if_seq_no
if include_source_on_error is not None:
__query["include_source_on_error"] = include_source_on_error
+ if op_type is not None:
+ __query["op_type"] = op_type
if pipeline is not None:
__query["pipeline"] = pipeline
if pretty is not None:
__query["pretty"] = pretty
if refresh is not None:
__query["refresh"] = refresh
+ if require_alias is not None:
+ __query["require_alias"] = require_alias
+ if require_data_stream is not None:
+ __query["require_data_stream"] = require_data_stream
if routing is not None:
__query["routing"] = routing
if timeout is not None:
@@ -5967,7 +5995,20 @@ def terms_enum(
)
@_rewrite_parameters(
- body_fields=("doc", "filter", "per_field_analyzer"),
+ body_fields=(
+ "doc",
+ "field_statistics",
+ "fields",
+ "filter",
+ "offsets",
+ "payloads",
+ "per_field_analyzer",
+ "positions",
+ "routing",
+ "term_statistics",
+ "version",
+ "version_type",
+ ),
)
def termvectors(
self,
@@ -6044,9 +6085,9 @@ def termvectors(
(the sum of document frequencies for all terms in this field). * The sum
of total term frequencies (the sum of total term frequencies of each term
in this field).
- :param fields: A comma-separated list or wildcard expressions of fields to include
- in the statistics. It is used as the default list unless a specific field
- list is provided in the `completion_fields` or `fielddata_fields` parameters.
+ :param fields: A list of fields to include in the statistics. It is used as the
+ default list unless a specific field list is provided in the `completion_fields`
+ or `fielddata_fields` parameters.
:param filter: Filter terms based on their tf-idf scores. This could be useful
in order find out a good characteristic vector of a document. This feature
works in a similar manner to the second phase of the More Like This Query.
@@ -6084,41 +6125,41 @@ def termvectors(
__body: t.Dict[str, t.Any] = body if body is not None else {}
if error_trace is not None:
__query["error_trace"] = error_trace
- if field_statistics is not None:
- __query["field_statistics"] = field_statistics
- if fields is not None:
- __query["fields"] = fields
if filter_path is not None:
__query["filter_path"] = filter_path
if human is not None:
__query["human"] = human
- if offsets is not None:
- __query["offsets"] = offsets
- if payloads is not None:
- __query["payloads"] = payloads
- if positions is not None:
- __query["positions"] = positions
if preference is not None:
__query["preference"] = preference
if pretty is not None:
__query["pretty"] = pretty
if realtime is not None:
__query["realtime"] = realtime
- if routing is not None:
- __query["routing"] = routing
- if term_statistics is not None:
- __query["term_statistics"] = term_statistics
- if version is not None:
- __query["version"] = version
- if version_type is not None:
- __query["version_type"] = version_type
if not __body:
if doc is not None:
__body["doc"] = doc
+ if field_statistics is not None:
+ __body["field_statistics"] = field_statistics
+ if fields is not None:
+ __body["fields"] = fields
if filter is not None:
__body["filter"] = filter
+ if offsets is not None:
+ __body["offsets"] = offsets
+ if payloads is not None:
+ __body["payloads"] = payloads
if per_field_analyzer is not None:
__body["per_field_analyzer"] = per_field_analyzer
+ if positions is not None:
+ __body["positions"] = positions
+ if routing is not None:
+ __body["routing"] = routing
+ if term_statistics is not None:
+ __body["term_statistics"] = term_statistics
+ if version is not None:
+ __body["version"] = version
+ if version_type is not None:
+ __body["version_type"] = version_type
if not __body:
__body = None # type: ignore[assignment]
__headers = {"accept": "application/json"}
diff --git a/elasticsearch/_sync/client/esql.py b/elasticsearch/_sync/client/esql.py
index 7d29224a9..7ef16cde1 100644
--- a/elasticsearch/_sync/client/esql.py
+++ b/elasticsearch/_sync/client/esql.py
@@ -35,6 +35,7 @@ class EsqlClient(NamespacedClient):
"params",
"profile",
"tables",
+ "wait_for_completion_timeout",
),
ignore_deprecated_options={"params"},
)
@@ -150,8 +151,6 @@ def async_query(
__query["keep_on_completion"] = keep_on_completion
if pretty is not None:
__query["pretty"] = pretty
- if wait_for_completion_timeout is not None:
- __query["wait_for_completion_timeout"] = wait_for_completion_timeout
if not __body:
if query is not None:
__body["query"] = query
@@ -169,6 +168,8 @@ def async_query(
__body["profile"] = profile
if tables is not None:
__body["tables"] = tables
+ if wait_for_completion_timeout is not None:
+ __body["wait_for_completion_timeout"] = wait_for_completion_timeout
__headers = {"accept": "application/json", "content-type": "application/json"}
return self.perform_request( # type: ignore[return-value]
"POST",
diff --git a/elasticsearch/_sync/client/indices.py b/elasticsearch/_sync/client/indices.py
index 939eeaf29..4f697b9a1 100644
--- a/elasticsearch/_sync/client/indices.py
+++ b/elasticsearch/_sync/client/indices.py
@@ -1622,7 +1622,9 @@ def exists_index_template(
name: str,
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ flat_settings: t.Optional[bool] = None,
human: t.Optional[bool] = None,
+ local: t.Optional[bool] = None,
master_timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
pretty: t.Optional[bool] = None,
) -> HeadApiResponse:
@@ -1637,6 +1639,10 @@ def exists_index_template(
:param name: Comma-separated list of index template names used to limit the request.
Wildcard (*) expressions are supported.
+ :param flat_settings: If true, returns settings in flat format.
+ :param local: If true, the request retrieves information from the local node
+ only. Defaults to false, which means information is retrieved from the master
+ node.
:param master_timeout: Period to wait for a connection to the master node. If
no response is received before the timeout expires, the request fails and
returns an error.
@@ -1650,8 +1656,12 @@ def exists_index_template(
__query["error_trace"] = error_trace
if filter_path is not None:
__query["filter_path"] = filter_path
+ if flat_settings is not None:
+ __query["flat_settings"] = flat_settings
if human is not None:
__query["human"] = human
+ if local is not None:
+ __query["local"] = local
if master_timeout is not None:
__query["master_timeout"] = master_timeout
if pretty is not None:
@@ -1801,9 +1811,6 @@ def field_usage_stats(
human: t.Optional[bool] = None,
ignore_unavailable: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
- wait_for_active_shards: t.Optional[
- t.Union[int, t.Union[str, t.Literal["all", "index-setting"]]]
- ] = None,
) -> ObjectApiResponse[t.Any]:
"""
.. raw:: html
@@ -1833,9 +1840,6 @@ def field_usage_stats(
in the statistics.
:param ignore_unavailable: If `true`, missing or closed indices are not included
in the response.
- :param wait_for_active_shards: The number of shard copies that must be active
- before proceeding with the operation. Set to all or any positive integer
- up to the total number of shards in the index (`number_of_replicas+1`).
"""
if index in SKIP_IN_PATH:
raise ValueError("Empty value passed for parameter 'index'")
@@ -1858,8 +1862,6 @@ def field_usage_stats(
__query["ignore_unavailable"] = ignore_unavailable
if pretty is not None:
__query["pretty"] = pretty
- if wait_for_active_shards is not None:
- __query["wait_for_active_shards"] = wait_for_active_shards
__headers = {"accept": "application/json"}
return self.perform_request( # type: ignore[return-value]
"GET",
@@ -3840,6 +3842,7 @@ def put_settings(
master_timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
preserve_existing: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
+ reopen: t.Optional[bool] = None,
timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
) -> ObjectApiResponse[t.Any]:
"""
@@ -3882,6 +3885,9 @@ def put_settings(
no response is received before the timeout expires, the request fails and
returns an error.
:param preserve_existing: If `true`, existing index settings remain unchanged.
+ :param reopen: Whether to close and reopen the index to apply non-dynamic settings.
+ If set to `true` the indices to which the settings are being applied will
+ be closed temporarily and then reopened in order to apply the changes.
:param timeout: Period to wait for a response. If no response is received before
the timeout expires, the request fails and returns an error.
"""
@@ -3919,6 +3925,8 @@ def put_settings(
__query["preserve_existing"] = preserve_existing
if pretty is not None:
__query["pretty"] = pretty
+ if reopen is not None:
+ __query["reopen"] = reopen
if timeout is not None:
__query["timeout"] = timeout
__body = settings if settings is not None else body
@@ -3986,7 +3994,7 @@ def put_template(
:param name: The name of the template
:param aliases: Aliases for the index.
- :param cause:
+ :param cause: User defined reason for creating/updating the index template
:param create: If true, this request cannot replace or update existing index
templates.
:param index_patterns: Array of wildcard expressions used to match the names
@@ -4224,6 +4232,7 @@ def reload_search_analyzers(
human: t.Optional[bool] = None,
ignore_unavailable: t.Optional[bool] = None,
pretty: t.Optional[bool] = None,
+ resource: t.Optional[str] = None,
) -> ObjectApiResponse[t.Any]:
"""
.. raw:: html
@@ -4251,6 +4260,7 @@ def reload_search_analyzers(
that are open, closed or both.
:param ignore_unavailable: Whether specified concrete indices should be ignored
when unavailable (missing or closed)
+ :param resource: Changed resource to reload analyzers from if applicable
"""
if index in SKIP_IN_PATH:
raise ValueError("Empty value passed for parameter 'index'")
@@ -4271,6 +4281,8 @@ def reload_search_analyzers(
__query["ignore_unavailable"] = ignore_unavailable
if pretty is not None:
__query["pretty"] = pretty
+ if resource is not None:
+ __query["resource"] = resource
__headers = {"accept": "application/json"}
return self.perform_request( # type: ignore[return-value]
"POST",
@@ -4507,6 +4519,7 @@ def rollover(
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
+ lazy: t.Optional[bool] = None,
mappings: t.Optional[t.Mapping[str, t.Any]] = None,
master_timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
pretty: t.Optional[bool] = None,
@@ -4563,6 +4576,9 @@ def rollover(
conditions are satisfied.
:param dry_run: If `true`, checks whether the current index satisfies the specified
conditions but does not perform a rollover.
+ :param lazy: If set to true, the rollover action will only mark a data stream
+ to signal that it needs to be rolled over at the next write. Only allowed
+ on data streams.
:param mappings: Mapping for fields in the index. If specified, this mapping
can include field names, field data types, and mapping paramaters.
:param master_timeout: Period to wait for a connection to the master node. If
@@ -4597,6 +4613,8 @@ def rollover(
__query["filter_path"] = filter_path
if human is not None:
__query["human"] = human
+ if lazy is not None:
+ __query["lazy"] = lazy
if master_timeout is not None:
__query["master_timeout"] = master_timeout
if pretty is not None:
@@ -4913,6 +4931,8 @@ def simulate_index_template(
self,
*,
name: str,
+ cause: t.Optional[str] = None,
+ create: t.Optional[bool] = None,
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
@@ -4930,6 +4950,10 @@ def simulate_index_template(
``_
:param name: Name of the index to simulate
+ :param cause: User defined reason for dry-run creating the new template for simulation
+ purposes
+ :param create: Whether the index template we optionally defined in the body should
+ only be dry-run added if new or can also replace an existing one
:param include_defaults: If true, returns all relevant default configurations
for the index template.
:param master_timeout: Period to wait for a connection to the master node. If
@@ -4941,6 +4965,10 @@ def simulate_index_template(
__path_parts: t.Dict[str, str] = {"name": _quote(name)}
__path = f'/_index_template/_simulate_index/{__path_parts["name"]}'
__query: t.Dict[str, t.Any] = {}
+ if cause is not None:
+ __query["cause"] = cause
+ if create is not None:
+ __query["create"] = create
if error_trace is not None:
__query["error_trace"] = error_trace
if filter_path is not None:
@@ -4983,6 +5011,7 @@ def simulate_template(
*,
name: t.Optional[str] = None,
allow_auto_create: t.Optional[bool] = None,
+ cause: t.Optional[str] = None,
composed_of: t.Optional[t.Sequence[str]] = None,
create: t.Optional[bool] = None,
data_stream: t.Optional[t.Mapping[str, t.Any]] = None,
@@ -5019,6 +5048,8 @@ def simulate_template(
via `actions.auto_create_index`. If set to `false`, then indices or data
streams matching the template must always be explicitly created, and may
never be automatically created.
+ :param cause: User defined reason for dry-run creating the new template for simulation
+ purposes
:param composed_of: An ordered list of component template names. Component templates
are merged in the order specified, meaning that the last component template
specified has the highest precedence.
@@ -5063,6 +5094,8 @@ def simulate_template(
__path = "/_index_template/_simulate"
__query: t.Dict[str, t.Any] = {}
__body: t.Dict[str, t.Any] = body if body is not None else {}
+ if cause is not None:
+ __query["cause"] = cause
if create is not None:
__query["create"] = create
if error_trace is not None:
diff --git a/elasticsearch/_sync/client/inference.py b/elasticsearch/_sync/client/inference.py
index 2ae2b637d..6bab33aec 100644
--- a/elasticsearch/_sync/client/inference.py
+++ b/elasticsearch/_sync/client/inference.py
@@ -321,6 +321,104 @@ def put(
path_parts=__path_parts,
)
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ def put_openai(
+ self,
+ *,
+ task_type: t.Union[
+ str, t.Literal["chat_completion", "completion", "text_embedding"]
+ ],
+ openai_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["openai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an OpenAI inference endpoint.
+
Create an inference endpoint to perform an inference task with the openai service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ NOTE: The `chat_completion` task type only supports streaming and only through
+ the _stream API.
+ :param openai_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `openai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `openai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if openai_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'openai_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "openai_inference_id": _quote(openai_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["openai_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_openai",
+ path_parts=__path_parts,
+ )
+
@_rewrite_parameters(
body_fields=("service", "service_settings"),
)
@@ -341,7 +439,7 @@ def put_watsonx(
.. raw:: html
Create a Watsonx inference endpoint.
-
Creates an inference endpoint to perform an inference task with the watsonxai service.
+
Create an inference endpoint to perform an inference task with the watsonxai service.
You need an IBM Cloud Databases for Elasticsearch deployment to use the watsonxai inference service.
You can provision one through the IBM catalog, the Cloud Databases CLI plug-in, the Cloud Databases API, or Terraform.
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
@@ -351,7 +449,7 @@ def put_watsonx(
Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
- ``_
+ ``_
:param task_type: The task type. The only valid task type for the model to perform
is `text_embedding`.
diff --git a/elasticsearch/_sync/client/ml.py b/elasticsearch/_sync/client/ml.py
index 3713ff741..d162abe82 100644
--- a/elasticsearch/_sync/client/ml.py
+++ b/elasticsearch/_sync/client/ml.py
@@ -3599,11 +3599,11 @@ def put_datafeed(
:param ignore_unavailable: If true, unavailable indices (missing or closed) are
ignored.
:param indexes: An array of index names. Wildcards are supported. If any of the
- indices are in remote clusters, the machine learning nodes must have the
- `remote_cluster_client` role.
+ indices are in remote clusters, the master nodes and the machine learning
+ nodes must have the `remote_cluster_client` role.
:param indices: An array of index names. Wildcards are supported. If any of the
- indices are in remote clusters, the machine learning nodes must have the
- `remote_cluster_client` role.
+ indices are in remote clusters, the master nodes and the machine learning
+ nodes must have the `remote_cluster_client` role.
:param indices_options: Specifies index expansion options that are used during
search
:param job_id: Identifier for the anomaly detection job.
diff --git a/elasticsearch/_sync/client/security.py b/elasticsearch/_sync/client/security.py
index 1f7c8bac2..5aac0202f 100644
--- a/elasticsearch/_sync/client/security.py
+++ b/elasticsearch/_sync/client/security.py
@@ -2867,12 +2867,12 @@ def oidc_authenticate(
)
@_rewrite_parameters(
- body_fields=("access_token", "refresh_token"),
+ body_fields=("token", "refresh_token"),
)
def oidc_logout(
self,
*,
- access_token: t.Optional[str] = None,
+ token: t.Optional[str] = None,
error_trace: t.Optional[bool] = None,
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
human: t.Optional[bool] = None,
@@ -2892,11 +2892,11 @@ def oidc_logout(
``_
- :param access_token: The access token to be invalidated.
+ :param token: The access token to be invalidated.
:param refresh_token: The refresh token to be invalidated.
"""
- if access_token is None and body is None:
- raise ValueError("Empty value passed for parameter 'access_token'")
+ if token is None and body is None:
+ raise ValueError("Empty value passed for parameter 'token'")
__path_parts: t.Dict[str, str] = {}
__path = "/_security/oidc/logout"
__query: t.Dict[str, t.Any] = {}
@@ -2910,8 +2910,8 @@ def oidc_logout(
if pretty is not None:
__query["pretty"] = pretty
if not __body:
- if access_token is not None:
- __body["access_token"] = access_token
+ if token is not None:
+ __body["token"] = token
if refresh_token is not None:
__body["refresh_token"] = refresh_token
__headers = {"accept": "application/json", "content-type": "application/json"}
diff --git a/elasticsearch/dsl/field.py b/elasticsearch/dsl/field.py
index 50f30b405..7fcc9ada5 100644
--- a/elasticsearch/dsl/field.py
+++ b/elasticsearch/dsl/field.py
@@ -1390,11 +1390,29 @@ def __init__(
class DenseVector(Field):
"""
- :arg element_type:
- :arg dims:
- :arg similarity:
- :arg index:
- :arg index_options:
+ :arg dims: Number of vector dimensions. Can't exceed `4096`. If `dims`
+ is not specified, it will be set to the length of the first vector
+ added to the field.
+ :arg element_type: The data type used to encode vectors. The supported
+ data types are `float` (default), `byte`, and `bit`. Defaults to
+ `float` if omitted.
+ :arg index: If `true`, you can search this field using the kNN search
+ API. Defaults to `True` if omitted.
+ :arg index_options: An optional section that configures the kNN
+ indexing algorithm. The HNSW algorithm has two internal parameters
+ that influence how the data structure is built. These can be
+ adjusted to improve the accuracy of results, at the expense of
+ slower indexing speed. This parameter can only be specified when
+ `index` is `true`.
+ :arg similarity: The vector similarity metric to use in kNN search.
+ Documents are ranked by their vector field's similarity to the
+ query vector. The `_score` of each document will be derived from
+ the similarity, in a way that ensures scores are positive and that
+ a larger score corresponds to a higher ranking. Defaults to
+ `l2_norm` when `element_type` is `bit` otherwise defaults to
+ `cosine`. `bit` vectors only support `l2_norm` as their
+ similarity metric. This parameter can only be specified when
+ `index` is `true`.
:arg meta: Metadata about the field.
:arg properties:
:arg ignore_above:
@@ -1413,13 +1431,16 @@ class DenseVector(Field):
def __init__(
self,
*args: Any,
- element_type: Union[str, "DefaultType"] = DEFAULT,
dims: Union[int, "DefaultType"] = DEFAULT,
- similarity: Union[str, "DefaultType"] = DEFAULT,
+ element_type: Union[Literal["bit", "byte", "float"], "DefaultType"] = DEFAULT,
index: Union[bool, "DefaultType"] = DEFAULT,
index_options: Union[
"types.DenseVectorIndexOptions", Dict[str, Any], "DefaultType"
] = DEFAULT,
+ similarity: Union[
+ Literal["cosine", "dot_product", "l2_norm", "max_inner_product"],
+ "DefaultType",
+ ] = DEFAULT,
meta: Union[Mapping[str, str], "DefaultType"] = DEFAULT,
properties: Union[Mapping[str, Field], "DefaultType"] = DEFAULT,
ignore_above: Union[int, "DefaultType"] = DEFAULT,
@@ -1432,16 +1453,16 @@ def __init__(
] = DEFAULT,
**kwargs: Any,
):
- if element_type is not DEFAULT:
- kwargs["element_type"] = element_type
if dims is not DEFAULT:
kwargs["dims"] = dims
- if similarity is not DEFAULT:
- kwargs["similarity"] = similarity
+ if element_type is not DEFAULT:
+ kwargs["element_type"] = element_type
if index is not DEFAULT:
kwargs["index"] = index
if index_options is not DEFAULT:
kwargs["index_options"] = index_options
+ if similarity is not DEFAULT:
+ kwargs["similarity"] = similarity
if meta is not DEFAULT:
kwargs["meta"] = meta
if properties is not DEFAULT:
@@ -1905,6 +1926,7 @@ class GeoShape(Field):
:arg coerce:
:arg ignore_malformed:
:arg ignore_z_value:
+ :arg index:
:arg orientation:
:arg strategy:
:arg doc_values:
@@ -1930,6 +1952,7 @@ def __init__(
coerce: Union[bool, "DefaultType"] = DEFAULT,
ignore_malformed: Union[bool, "DefaultType"] = DEFAULT,
ignore_z_value: Union[bool, "DefaultType"] = DEFAULT,
+ index: Union[bool, "DefaultType"] = DEFAULT,
orientation: Union[Literal["right", "left"], "DefaultType"] = DEFAULT,
strategy: Union[Literal["recursive", "term"], "DefaultType"] = DEFAULT,
doc_values: Union[bool, "DefaultType"] = DEFAULT,
@@ -1957,6 +1980,8 @@ def __init__(
kwargs["ignore_malformed"] = ignore_malformed
if ignore_z_value is not DEFAULT:
kwargs["ignore_z_value"] = ignore_z_value
+ if index is not DEFAULT:
+ kwargs["index"] = index
if orientation is not DEFAULT:
kwargs["orientation"] = orientation
if strategy is not DEFAULT:
@@ -3497,8 +3522,18 @@ def __init__(
class SemanticText(Field):
"""
- :arg inference_id: (required)
:arg meta:
+ :arg inference_id: Inference endpoint that will be used to generate
+ embeddings for the field. This parameter cannot be updated. Use
+ the Create inference API to create the endpoint. If
+ `search_inference_id` is specified, the inference endpoint will
+ only be used at index time. Defaults to `.elser-2-elasticsearch`
+ if omitted.
+ :arg search_inference_id: Inference endpoint that will be used to
+ generate embeddings at query time. You can update this parameter
+ by using the Update mapping API. Use the Create inference API to
+ create the endpoint. If not specified, the inference endpoint
+ defined by inference_id will be used at both index and query time.
"""
name = "semantic_text"
@@ -3506,14 +3541,17 @@ class SemanticText(Field):
def __init__(
self,
*args: Any,
- inference_id: Union[str, "DefaultType"] = DEFAULT,
meta: Union[Mapping[str, str], "DefaultType"] = DEFAULT,
+ inference_id: Union[str, "DefaultType"] = DEFAULT,
+ search_inference_id: Union[str, "DefaultType"] = DEFAULT,
**kwargs: Any,
):
- if inference_id is not DEFAULT:
- kwargs["inference_id"] = inference_id
if meta is not DEFAULT:
kwargs["meta"] = meta
+ if inference_id is not DEFAULT:
+ kwargs["inference_id"] = inference_id
+ if search_inference_id is not DEFAULT:
+ kwargs["search_inference_id"] = search_inference_id
super().__init__(*args, **kwargs)
diff --git a/elasticsearch/dsl/types.py b/elasticsearch/dsl/types.py
index 4ea6d8361..7474769c6 100644
--- a/elasticsearch/dsl/types.py
+++ b/elasticsearch/dsl/types.py
@@ -364,34 +364,57 @@ def __init__(
class DenseVectorIndexOptions(AttrDict[Any]):
"""
- :arg type: (required)
- :arg m:
- :arg ef_construction:
- :arg confidence_interval:
- """
-
- type: Union[str, DefaultType]
- m: Union[int, DefaultType]
- ef_construction: Union[int, DefaultType]
+ :arg type: (required) The type of kNN algorithm to use.
+ :arg confidence_interval: The confidence interval to use when
+ quantizing the vectors. Can be any value between and including
+ `0.90` and `1.0` or exactly `0`. When the value is `0`, this
+ indicates that dynamic quantiles should be calculated for
+ optimized quantization. When between `0.90` and `1.0`, this value
+ restricts the values used when calculating the quantization
+ thresholds. For example, a value of `0.95` will only use the
+ middle `95%` of the values when calculating the quantization
+ thresholds (e.g. the highest and lowest `2.5%` of values will be
+ ignored). Defaults to `1/(dims + 1)` for `int8` quantized vectors
+ and `0` for `int4` for dynamic quantile calculation. Only
+ applicable to `int8_hnsw`, `int4_hnsw`, `int8_flat`, and
+ `int4_flat` index types.
+ :arg ef_construction: The number of candidates to track while
+ assembling the list of nearest neighbors for each new node. Only
+ applicable to `hnsw`, `int8_hnsw`, and `int4_hnsw` index types.
+ Defaults to `100` if omitted.
+ :arg m: The number of neighbors each node will be connected to in the
+ HNSW graph. Only applicable to `hnsw`, `int8_hnsw`, and
+ `int4_hnsw` index types. Defaults to `16` if omitted.
+ """
+
+ type: Union[
+ Literal["flat", "hnsw", "int4_flat", "int4_hnsw", "int8_flat", "int8_hnsw"],
+ DefaultType,
+ ]
confidence_interval: Union[float, DefaultType]
+ ef_construction: Union[int, DefaultType]
+ m: Union[int, DefaultType]
def __init__(
self,
*,
- type: Union[str, DefaultType] = DEFAULT,
- m: Union[int, DefaultType] = DEFAULT,
- ef_construction: Union[int, DefaultType] = DEFAULT,
+ type: Union[
+ Literal["flat", "hnsw", "int4_flat", "int4_hnsw", "int8_flat", "int8_hnsw"],
+ DefaultType,
+ ] = DEFAULT,
confidence_interval: Union[float, DefaultType] = DEFAULT,
+ ef_construction: Union[int, DefaultType] = DEFAULT,
+ m: Union[int, DefaultType] = DEFAULT,
**kwargs: Any,
):
if type is not DEFAULT:
kwargs["type"] = type
- if m is not DEFAULT:
- kwargs["m"] = m
- if ef_construction is not DEFAULT:
- kwargs["ef_construction"] = ef_construction
if confidence_interval is not DEFAULT:
kwargs["confidence_interval"] = confidence_interval
+ if ef_construction is not DEFAULT:
+ kwargs["ef_construction"] = ef_construction
+ if m is not DEFAULT:
+ kwargs["m"] = m
super().__init__(kwargs)
From cb1c14f794ad3f48941688f26956bd0aa1c0a8a2 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 28 Mar 2025 15:23:22 +0000
Subject: [PATCH 07/57] Use class-based queries and type-hinted documents in
DSL documentation examples (#2857) (#2862)
* Use class-based queries and type-hinted documents in DSL documentation examples
* DSL migrating section
(cherry picked from commit d49252487daab1e3e5fd8667714c2a369e7de4e5)
Co-authored-by: Miguel Grinberg
---
docs/reference/dsl_how_to_guides.md | 208 +++++++++++++++-------------
docs/reference/dsl_migrating.md | 35 +++++
docs/reference/dsl_tutorials.md | 43 +++---
docs/reference/elasticsearch-dsl.md | 14 +-
docs/reference/toc.yml | 1 +
elasticsearch/dsl/search_base.py | 19 ++-
6 files changed, 189 insertions(+), 131 deletions(-)
create mode 100644 docs/reference/dsl_migrating.md
diff --git a/docs/reference/dsl_how_to_guides.md b/docs/reference/dsl_how_to_guides.md
index 08e16b28c..93dc8d9a1 100644
--- a/docs/reference/dsl_how_to_guides.md
+++ b/docs/reference/dsl_how_to_guides.md
@@ -23,7 +23,7 @@ The `Search` object represents the entire search request:
* additional parameters
* associated client
-The API is designed to be chainable. With the exception of the aggregations functionality this means that the `Search` object is immutable -all changes to the object will result in a shallow copy being created which contains the changes. This means you can safely pass the `Search` object to foreign code without fear of it modifying your objects as long as it sticks to the `Search` object APIs.
+The API is designed to be chainable. With the exception of the aggregations functionality this means that the `Search` object is immutable -all changes to the object will result in a shallow copy being created which contains the changes. You can safely pass the `Search` object to foreign code without fear of it modifying your objects as long as it sticks to the `Search` object APIs.
You can pass an instance of the [elasticsearch client](https://elasticsearch-py.readthedocs.io/) when instantiating the `Search` object:
@@ -51,7 +51,7 @@ All methods return a *copy* of the object, making it safe to pass to outside cod
The API is chainable, allowing you to combine multiple method calls in one statement:
```python
-s = Search().using(client).query("match", title="python")
+s = Search().using(client).query(Match("title", "python"))
```
To send the request to Elasticsearch:
@@ -67,9 +67,9 @@ for hit in s:
print(hit.title)
```
-Search results will be cached. Subsequent calls to `execute` or trying to iterate over an already executed `Search` object will not trigger additional requests being sent to Elasticsearch. To force a request specify `ignore_cache=True` when calling `execute`.
+Search results will be cached. Subsequent calls to `execute` or trying to iterate over an already executed `Search` object will not trigger additional requests being sent to Elasticsearch. To force a new request to be issued specify `ignore_cache=True` when calling `execute`.
-For debugging purposes you can serialize the `Search` object to a `dict` explicitly:
+For debugging purposes you can serialize the `Search` object to a `dict` with the raw Elasticsearch request:
```python
print(s.to_dict())
@@ -80,32 +80,28 @@ print(s.to_dict())
You can delete the documents matching a search by calling `delete` on the `Search` object instead of `execute` like this:
```python
-s = Search(index='i').query("match", title="python")
+s = Search(index='i').query(Match("title", "python"))
response = s.delete()
```
#### Queries [_queries]
-The library provides classes for all Elasticsearch query types. Pass all the parameters as keyword arguments. The classes accept any keyword arguments, the dsl then takes all arguments passed to the constructor and serializes them as top-level keys in the resulting dictionary (and thus the resulting json being sent to elasticsearch). This means that there is a clear one-to-one mapping between the raw query and its equivalent in the DSL:
+The `elasticsearch.dsl.query` module provides classes for all Elasticsearch query types. These classes accept keyword arguments in their constructors, which are serialized to the appropriate format to be sent to Elasticsearch. There is a clear one-to-one mapping between the raw query and its equivalent class-based version:
```python
-from elasticsearch.dsl.query import MultiMatch, Match
+>>> from elasticsearch.dsl.query import MultiMatch, Match
-# {"multi_match": {"query": "python django", "fields": ["title", "body"]}}
-MultiMatch(query='python django', fields=['title', 'body'])
+>>> q = MultiMatch(query='python django', fields=['title', 'body'])
+>>> q.to_dict()
+{'multi_match': {'query': 'python django', 'fields': ['title', 'body']}}
-# {"match": {"title": {"query": "web framework", "type": "phrase"}}}
-Match(title={"query": "web framework", "type": "phrase"})
+>>> q = Match("title", {"query": "web framework", "type": "phrase"})
+>>> q.to_dict()
+{'match': {'title': {'query': 'web framework', 'type': 'phrase'}}}
```
-::::{note}
-In some cases this approach is not possible due to python’s restriction on identifiers - for example if your field is called `@timestamp`. In that case you have to fall back to unpacking a dictionary: `Range(*+ {'@timestamp': {'lt': 'now'}})`
-
-::::
-
-
-You can use the `Q` shortcut to construct the instance using a name with parameters or the raw `dict`:
+An alternative to the class-based queries is to use the `Q` shortcut, passing a query name followed by its parameters, or the raw query as a `dict`:
```python
from elasticsearch.dsl import Q
@@ -114,20 +110,20 @@ Q("multi_match", query='python django', fields=['title', 'body'])
Q({"multi_match": {"query": "python django", "fields": ["title", "body"]}})
```
-To add the query to the `Search` object, use the `.query()` method:
+To add a query to the `Search` object, use the `.query()` method. This works with class-based or `Q` queries:
```python
q = Q("multi_match", query='python django', fields=['title', 'body'])
s = s.query(q)
```
-The method also accepts all the parameters as the `Q` shortcut:
+As a shortcut the `query()` method also accepts all the parameters of the `Q` shortcut directly:
```python
s = s.query("multi_match", query='python django', fields=['title', 'body'])
```
-If you already have a query object, or a `dict` representing one, you can just override the query used in the `Search` object:
+If you already have a query object, or a `dict` representing one, you can assign it to the `query` attribute of a `Search` object to add it to it, replacing any previously configured queries:
```python
s.query = Q('bool', must=[Q('match', title='python'), Q('match', body='best')])
@@ -136,7 +132,7 @@ s.query = Q('bool', must=[Q('match', title='python'), Q('match', body='best')])
#### Dotted fields [_dotted_fields]
-Sometimes you want to refer to a field within another field, either as a multi-field (`title.keyword`) or in a structured `json` document like `address.city`. To make it easier, the `Q` shortcut (as well as the `query`, `filter`, and `exclude` methods on `Search` class) allows you to use `_+` (double underscore) in place of a dot in a keyword argument:
+Sometimes you want to refer to a field within another field, either as a multi-field (`title.keyword`) or in a structured `json` document like `address.city`. This is not a problem when using class-based queries, but when working without classes it is often required to pass field names as keyword arguments. To make this easier, you can use `__` (double underscore) in place of a dot in a keyword argument:
```python
s = Search()
@@ -144,7 +140,7 @@ s = s.filter('term', category__keyword='Python')
s = s.query('match', address__city='prague')
```
-Alternatively you can always fall back to python’s kwarg unpacking if you prefer:
+Alternatively you can use Python’s keyword argument unpacking:
```python
s = Search()
@@ -155,20 +151,23 @@ s = s.query('match', **{'address.city': 'prague'})
#### Query combination [_query_combination]
-Query objects can be combined using logical operators:
+Query objects can be combined using logical operators `|`, `&` and `~`:
```python
-Q("match", title='python') | Q("match", title='django')
-# {"bool": {"should": [...]}}
+>>> q = Match("title", "python") | Match("title", "django")
+>>> q.to_dict()
+{'bool': {'should': [{'match': {'title': 'python'}}, {'match': {'title': 'django'}}]}}
-Q("match", title='python') & Q("match", title='django')
-# {"bool": {"must": [...]}}
+>>> q = Match("title", "python") & Match("title", "django")
+>>> q.to_dict()
+{'bool': {'must': [{'match': {'title': 'python'}}, {'match': {'title': 'django'}}]}}
-~Q("match", title="python")
-# {"bool": {"must_not": [...]}}
+>>> q = ~Match("title", "python")
+>>> q.to_dict()
+{'bool': {'must_not': [{'match': {'title': 'python'}}]}}
```
-When you call the `.query()` method multiple times, the `&` operator will be used internally:
+When you call the `.query()` method multiple times, the `&` operator will be used internally to combine all the queries:
```python
s = s.query().query()
@@ -193,48 +192,64 @@ s = Search().query(q)
If you want to add a query in a [filter context](docs-content://explore-analyze/query-filter/languages/querydsl.md) you can use the `filter()` method to make things easier:
```python
+from elasticsearch.dsl.query import Terms
+
s = Search()
-s = s.filter('terms', tags=['search', 'python'])
+s = s.filter(Terms("tags", ['search', 'python']))
```
Behind the scenes this will produce a `Bool` query and place the specified `terms` query into its `filter` branch, making it equivalent to:
```python
+from elasticsearch.dsl.query import Terms, Bool
+
s = Search()
-s = s.query('bool', filter=[Q('terms', tags=['search', 'python'])])
+s = s.query(Bool(filter=[Terms("tags", ["search", "python"])]))
```
-If you want to use the post_filter element for faceted navigation, use the `.post_filter()` method.
+If you want to use the `post_filter` element for faceted navigation, use the `.post_filter()` method.
-You can also `exclude()` items from your query like this:
+The `exclude()` method works like `filter()`, but it applies the query as negated:
```python
s = Search()
-s = s.exclude('terms', tags=['search', 'python'])
+s = s.exclude(Terms("tags", ['search', 'python']))
```
-which is shorthand for: `s = s.query('bool', filter=[~Q('terms', tags=['search', 'python'])])`
+which is shorthand for:
+
+```python
+s = s.query(Bool(filter=[~Terms("tags", ["search", "python"])]))
+```
#### Aggregations [_aggregations]
-To define an aggregation, you can use the `A` shortcut:
+As with queries, there are classes that represent each aggregation type, all accessible through the `elasticsearch.dsl.aggs` module:
+
+```python
+from elasticsearch.dsl import aggs
+
+a = aggs.Terms(field="tags")
+# {"terms": {"field": "tags"}}
+```
+
+It is also possible to define an aggregation using the `A` shortcut:
```python
from elasticsearch.dsl import A
A('terms', field='tags')
-# {"terms": {"field": "tags"}}
```
To nest aggregations, you can use the `.bucket()`, `.metric()` and `.pipeline()` methods:
```python
-a = A('terms', field='category')
+a = aggs.Terms(field="category")
# {'terms': {'field': 'category'}}
-a.metric('clicks_per_category', 'sum', field='clicks')\
- .bucket('tags_per_category', 'terms', field='tags')
+a.metric("clicks_per_category", aggs.Sum(field="clicks")) \
+ .bucket("tags_per_category", aggs.Terms(field="tags"))
# {
# 'terms': {'field': 'category'},
# 'aggs': {
@@ -248,8 +263,8 @@ To add aggregations to the `Search` object, use the `.aggs` property, which acts
```python
s = Search()
-a = A('terms', field='category')
-s.aggs.bucket('category_terms', a)
+a = aggs.Terms(field="category")
+s.aggs.bucket("category_terms", a)
# {
# 'aggs': {
# 'category_terms': {
@@ -265,10 +280,10 @@ or
```python
s = Search()
-s.aggs.bucket('articles_per_day', 'date_histogram', field='publish_date', interval='day')\
- .metric('clicks_per_day', 'sum', field='clicks')\
- .pipeline('moving_click_average', 'moving_avg', buckets_path='clicks_per_day')\
- .bucket('tags_per_day', 'terms', field='tags')
+s.aggs.bucket("articles_per_day", aggs.DateHistogram(field="publish_date", interval="day")) \
+ .metric("clicks_per_day", aggs.Sum(field="clicks")) \
+ .pipeline("moving_click_average", aggs.MovingAvg(buckets_path="clicks_per_day")) \
+ .bucket("tags_per_day", aggs.Terms(field="tags"))
s.to_dict()
# {
@@ -290,9 +305,9 @@ You can access an existing bucket by its name:
```python
s = Search()
-s.aggs.bucket('per_category', 'terms', field='category')
-s.aggs['per_category'].metric('clicks_per_category', 'sum', field='clicks')
-s.aggs['per_category'].bucket('tags_per_category', 'terms', field='tags')
+s.aggs.bucket("per_category", aggs.Terms(field="category"))
+s.aggs["per_category"].metric("clicks_per_category", aggs.Sum(field="clicks"))
+s.aggs["per_category"].bucket("tags_per_category", aggs.Terms(field="tags"))
```
::::{note}
@@ -301,7 +316,7 @@ When chaining multiple aggregations, there is a difference between what `.bucket
::::
-As opposed to other methods on the `Search` objects, defining aggregations is done in-place (does not return a copy).
+As opposed to other methods on the `Search` objects, aggregations are defined in-place, without returning a new copy.
#### K-Nearest Neighbor Searches [_k_nearest_neighbor_searches]
@@ -348,7 +363,7 @@ s = s.sort()
#### Pagination [_pagination]
-To specify the from/size parameters, use the Python slicing API:
+To specify the from/size parameters, apply the standard Python slicing operator on the `Search` instance:
```python
s = s[10:20]
@@ -417,7 +432,7 @@ The first argument is the name of the suggestions (name under which it will be r
To collapse search results use the `collapse` method on your `Search` object:
```python
-s = Search().query("match", message="GET /search")
+s = Search().query(Match("message", "GET /search"))
# collapse results by user_id
s = s.collapse("user_id")
```
@@ -526,11 +541,11 @@ If you want to inspect the contents of the `response` objects, just use its `to_
#### Hits [_hits]
-To access to the hits returned by the search, access the `hits` property or just iterate over the `Response` object:
+To access the hits returned by the search, use the `hits` property or just iterate over the `Response` object:
```python
response = s.execute()
-print('Total %d hits found.' % response.hits.total)
+print(f"Total {response.hits.total} hits found.")
for h in response:
print(h.title, h.body)
```
@@ -549,8 +564,7 @@ The individual hits is wrapped in a convenience class that allows attribute acce
```python
response = s.execute()
h = response.hits[0]
-print('/%s/%s/%s returned with score %f' % (
- h.meta.index, h.meta.doc_type, h.meta.id, h.meta.score))
+print(f"/{h.meta.index}/{h.meta.doc_type}/{h.meta.id} returned with score {h.meta.score}")
```
::::{note}
@@ -577,11 +591,12 @@ If you need to execute multiple searches at the same time you can use the `Multi
```python
from elasticsearch.dsl import MultiSearch, Search
+from elasticsearch.dsl.query import Term
ms = MultiSearch(index='blogs')
-ms = ms.add(Search().filter('term', tags='python'))
-ms = ms.add(Search().filter('term', tags='elasticsearch'))
+ms = ms.add(Search().filter(Term("tags", "python")))
+ms = ms.add(Search().filter(Term("tags", 'elasticsearch')))
responses = ms.execute()
@@ -653,9 +668,9 @@ class Post(Document):
#### Data types [_data_types]
-The `Document` instances use native python types like `str` and `datetime`. In case of `Object` or `Nested` fields an instance of the `InnerDoc` subclass is used, as in the `add_comment` method in the above example where we are creating an instance of the `Comment` class.
+The `Document` instances use native python types such as `str` and `datetime` for its attributes. In case of `Object` or `Nested` fields an instance of the `InnerDoc` subclass is used, as in the `add_comment` method in the above example, where we are creating an instance of the `Comment` class.
-There are some specific types that were created as part of this library to make working with some field types easier, for example the `Range` object used in any of the [range fields](elasticsearch://reference/elasticsearch/mapping-reference/range.md):
+There are some specific types that were created to make working with some field types easier, for example the `Range` object used in any of the [range fields](elasticsearch://reference/elasticsearch/mapping-reference/range.md):
```python
from elasticsearch.dsl import Document, DateRange, Keyword, Range
@@ -664,7 +679,6 @@ class RoomBooking(Document):
room = Keyword()
dates = DateRange()
-
rb = RoomBooking(
room='Conference Room II',
dates=Range(
@@ -700,7 +714,7 @@ class Post(Document):
It is important to note that when using `Field` subclasses such as `Text`, `Date` and `Boolean`, they must be given in the right-side of an assignment, as shown in examples above. Using these classes as type hints will result in errors.
-Python types are mapped to their corresponding field type according to the following table:
+Python types are mapped to their corresponding field types according to the following table:
| Python type | DSL field |
| --- | --- |
@@ -740,18 +754,18 @@ class Post(Document):
comments: List[Comment] # same as comments = Nested(Comment, required=True)
```
-Unfortunately it is impossible to have Python type hints that uniquely identify every possible Elasticsearch field type. To choose a field type that is different than the ones in the table above, the field instance can be added explicitly as a right-side assignment in the field declaration. The next example creates a field that is typed as `Optional[str]`, but is mapped to `Keyword` instead of `Text`:
+Unfortunately it is impossible to have Python type hints that uniquely identify every possible Elasticsearch field type. To choose a field type that is different than the one that is assigned according to the table above, the desired field instance can be added explicitly as a right-side assignment in the field declaration. The next example creates a field that is typed as `Optional[str]`, but is mapped to `Keyword` instead of `Text`:
```python
class MyDocument(Document):
category: Optional[str] = Keyword()
```
-This form can also be used when additional options need to be given to initialize the field, such as when using custom analyzer settings or changing the `required` default:
+This form can also be used when additional options need to be given to initialize the field, such as when using custom analyzer settings:
```python
class Comment(InnerDoc):
- content: str = Text(analyzer='snowball', required=True)
+ content: str = Text(analyzer='snowball')
```
When using type hints as above, subclasses of `Document` and `InnerDoc` inherit some of the behaviors associated with Python dataclasses, as defined by [PEP 681](https://peps.python.org/pep-0681/) and the [dataclass_transform decorator](https://typing.readthedocs.io/en/latest/spec/dataclasses.html#dataclass-transform). To add per-field dataclass options such as `default` or `default_factory`, the `mapped_field()` wrapper can be used on the right side of a typed field declaration:
@@ -761,12 +775,12 @@ class MyDocument(Document):
title: str = mapped_field(default="no title")
created_at: datetime = mapped_field(default_factory=datetime.now)
published: bool = mapped_field(default=False)
- category: str = mapped_field(Keyword(required=True), default="general")
+ category: str = mapped_field(Keyword(), default="general")
```
When using the `mapped_field()` wrapper function, an explicit field type instance can be passed as a first positional argument, as the `category` field does in the example above.
-Static type checkers such as [mypy](https://mypy-lang.org/) and [pyright](https://github.com/microsoft/pyright) can use the type hints and the dataclass-specific options added to the `mapped_field()` function to improve type inference and provide better real-time suggestions in IDEs.
+Static type checkers such as [mypy](https://mypy-lang.org/) and [pyright](https://github.com/microsoft/pyright) can use the type hints and the dataclass-specific options added to the `mapped_field()` function to improve type inference and provide better real-time code completion and suggestions in IDEs.
One situation in which type checkers can’t infer the correct type is when using fields as class attributes. Consider the following example:
@@ -804,7 +818,7 @@ The `InstrumentedField` objects returned when fields are accessed as class attri
s = MyDocument.search().sort(-MyDocument.created_at, MyDocument.title)
```
-When specifying sorting order, the `{{plus}}` and `-` unary operators can be used on the class field attributes to indicate ascending and descending order.
+When specifying sorting order, the `+` and `-` unary operators can be used on the class field attributes to indicate ascending and descending order.
Finally, the `ClassVar` annotation can be used to define a regular class attribute that should not be mapped to the Elasticsearch index:
@@ -812,9 +826,8 @@ Finally, the `ClassVar` annotation can be used to define a regular class attribu
from typing import ClassVar
class MyDoc(Document):
- title: M[str] created_at: M[datetime] =
- mapped_field(default_factory=datetime.now) my_var:
- ClassVar[str] # regular class variable, ignored by Elasticsearch
+ title: M[str] created_at: M[datetime] = mapped_field(default_factory=datetime.now)
+ my_var: ClassVar[str] # regular class variable, ignored by Elasticsearch
```
@@ -1050,13 +1063,13 @@ You can use standard Python inheritance to extend models, this can be useful in
```python
class User(InnerDoc):
- username = Text(fields={'keyword': Keyword()})
- email = Text()
+ username: str = mapped_field(Text(fields={'keyword': Keyword()}))
+ email: str
class BaseDocument(Document):
- created_by = Object(User)
- created_date = Date()
- last_updated = Date()
+ created_by: User
+ created_date: datetime
+ last_updated: datetime
def save(**kwargs):
if not self.created_date:
@@ -1101,7 +1114,7 @@ blogs.document(Post)
# can also be used as class decorator when defining the Document
@blogs.document
class Post(Document):
- title = Text()
+ title: str
# You can attach custom analyzers to the index
@@ -1138,9 +1151,15 @@ dev_blogs.setting(number_of_shards=1)
#### IndexTemplate [index-template]
-The DSL module also exposes an option to manage [index templates](docs-content://manage-data/data-store/templates.md) in elasticsearch using the `IndexTemplate` class which has very similar API to `Index`.
+The DSL module also exposes an option to manage [index templates](docs-content://manage-data/data-store/templates.md) in elasticsearch using the `ComposableIndexTemplate` and `IndexTemplate` classes, which have very similar API to `Index`.
+
+::::{note}
+Composable index templates should be always be preferred over the legacy index templates, since the latter are deprecated.
-Once an index template is saved in elasticsearch it’s contents will be automatically applied to new indices (existing indices are completely unaffected by templates) that match the template pattern (any index starting with `blogs-` in our example), even if the index is created automatically upon indexing a document into that index.
+::::
+
+
+Once an index template is saved in Elasticsearch its contents will be automatically applied to new indices (existing indices are completely unaffected by templates) that match the template pattern (any index starting with `blogs-` in our example), even if the index is created automatically upon indexing a document into that index.
Potential workflow for a set of time based indices governed by a single template:
@@ -1151,14 +1170,11 @@ from elasticsearch.dsl import Document, Date, Text
class Log(Document):
- content = Text()
- timestamp = Date()
+ content: str
+ timestamp: datetime
class Index:
name = "logs-*"
- settings = {
- "number_of_shards": 2
- }
def save(self, **kwargs):
# assign now if no timestamp given
@@ -1170,7 +1186,7 @@ class Log(Document):
return super().save(**kwargs)
# once, as part of application setup, during deploy/migrations:
-logs = Log._index.as_template('logs', order=0)
+logs = Log._index.as_composable_template('logs', priority=100)
logs.save()
# to perform search across all logs:
@@ -1184,12 +1200,6 @@ search = Log.search()
The library comes with a simple abstraction aimed at helping you develop faceted navigation for your data.
-::::{note}
-This API is experimental and will be subject to change. Any feedback is welcome.
-
-::::
-
-
### Configuration [_configuration_2]
You can provide several configuration options (as class attributes) when declaring a `FacetedSearch` subclass:
@@ -1316,7 +1326,7 @@ All methods return a *copy* of the object, making it safe to pass to outside cod
The API is chainable, allowing you to combine multiple method calls in one statement:
```python
-ubq = UpdateByQuery().using(client).query("match", title="python")
+ubq = UpdateByQuery().using(client).query(Match("title", python"))
```
To send the request to Elasticsearch:
@@ -1444,8 +1454,9 @@ Use the `AsyncSearch` class to perform asynchronous searches.
```python
from elasticsearch.dsl import AsyncSearch
+from elasticsearch.dsl.query import Match
-s = AsyncSearch().query("match", title="python")
+s = AsyncSearch().query(Match("title", "python"))
async for hit in s:
print(hit.title)
```
@@ -1453,7 +1464,7 @@ async for hit in s:
Instead of using the `AsyncSearch` object as an asynchronous iterator, you can explicitly call the `execute()` method to get a `Response` object.
```python
-s = AsyncSearch().query("match", title="python")
+s = AsyncSearch().query(Match("title", "python"))
response = await s.execute()
for hit in response:
print(hit.title)
@@ -1463,11 +1474,12 @@ An `AsyncMultiSearch` is available as well.
```python
from elasticsearch.dsl import AsyncMultiSearch
+from elasticsearch.dsl.query import Term
ms = AsyncMultiSearch(index='blogs')
-ms = ms.add(AsyncSearch().filter('term', tags='python'))
-ms = ms.add(AsyncSearch().filter('term', tags='elasticsearch'))
+ms = ms.add(AsyncSearch().filter(Term("tags", "python")))
+ms = ms.add(AsyncSearch().filter(Term("tags", "elasticsearch")))
responses = await ms.execute()
diff --git a/docs/reference/dsl_migrating.md b/docs/reference/dsl_migrating.md
new file mode 100644
index 000000000..ef4bd9f23
--- /dev/null
+++ b/docs/reference/dsl_migrating.md
@@ -0,0 +1,35 @@
+# Migrating from the `elasticsearch-dsl` package [_migrating_from_elasticsearch_dsl_package]
+
+In the past the Elasticsearch Python DSL module was distributed as a standalone package called `elasticsearch-dsl`. This package is now deprecated, since all its functionality has been integrated into the main Python client. We recommend all developers to migrate their applications and eliminate their dependency on the `elasticsearch-dsl` package.
+
+To migrate your application, all references to `elasticsearch_dsl` as a top-level package must be changed to `elasticsearch.dsl`. In other words, the underscore from the package name should be replaced by a period.
+
+Here are a few examples:
+
+```python
+# from:
+from elasticsearch_dsl import Date, Document, InnerDoc, Text, connections
+# to:
+from elasticsearch.dsl import Date, Document, InnerDoc, Text, connections
+
+# from:
+from elasticsearch_dsl.query import MultiMatch
+# to:
+from elasticsearch.dsl.query import MultiMatch
+
+# from:
+import elasticsearch_dsl as dsl
+# to:
+from elasticsearch import dsl
+
+# from:
+import elasticsearch_dsl
+# to:
+from elasticsearch import dsl as elasticsearch_dsl
+
+# from:
+import elasticsearch_dsl
+# to:
+from elasticsearch import dsl
+# and replace all references to "elasticsearch_dsl" in the code with "dsl"
+```
diff --git a/docs/reference/dsl_tutorials.md b/docs/reference/dsl_tutorials.md
index 7b72bc04e..77992587b 100644
--- a/docs/reference/dsl_tutorials.md
+++ b/docs/reference/dsl_tutorials.md
@@ -47,17 +47,17 @@ Let’s rewrite the example using the DSL module:
```python
from elasticsearch import Elasticsearch
-from elasticsearch.dsl import Search
+from elasticsearch.dsl import Search, query, aggs
client = Elasticsearch("https://localhost:9200")
s = Search(using=client, index="my-index") \
- .filter("term", category="search") \
- .query("match", title="python") \
- .exclude("match", description="beta")
+ .query(query.Match("title", "python")) \
+ .filter(query.Term("category", "search")) \
+ .exclude(query.Match("description", "beta"))
-s.aggs.bucket('per_tag', 'terms', field='tags') \
- .metric('max_lines', 'max', field='lines')
+s.aggs.bucket('per_tag', aggs.Terms(field="tags")) \
+ .metric('max_lines', aggs.Max(field='lines'))
response = s.execute()
@@ -68,9 +68,9 @@ for tag in response.aggregations.per_tag.buckets:
print(tag.key, tag.max_lines.value)
```
-As you see, the library took care of:
+As you see, the DSL module took care of:
-* creating appropriate `Query` objects by name (eq. "match")
+* creating appropriate `Query` objects from classes
* composing queries into a compound `bool` query
* putting the `term` query in a filter context of the `bool` query
* providing a convenient access to response data
@@ -89,11 +89,11 @@ from elasticsearch.dsl import Document, Date, Integer, Keyword, Text, connection
connections.create_connection(hosts="https://localhost:9200")
class Article(Document):
- title = Text(analyzer='snowball', fields={'raw': Keyword()})
- body = Text(analyzer='snowball')
- tags = Keyword()
- published_from = Date()
- lines = Integer()
+ title: str = mapped_field(Text(analyzer='snowball', fields={'raw': Keyword()}))
+ body: str = mapped_field(Text(analyzer='snowball'))
+ tags: str = mapped_field(Keyword())
+ published_from: datetime
+ lines: int
class Index:
name = 'blog'
@@ -101,7 +101,7 @@ class Article(Document):
"number_of_shards": 2,
}
- def save(self, ** kwargs):
+ def save(self, **kwargs):
self.lines = len(self.body.split())
return super(Article, self).save(** kwargs)
@@ -127,7 +127,7 @@ print(connections.get_connection().cluster.health())
In this example you can see:
* providing a default connection
-* defining fields with mapping configuration
+* defining fields with Python type hints and additional mapping configuration when necessary
* setting index name
* defining custom methods
* overriding the built-in `.save()` method to hook into the persistence life cycle
@@ -141,12 +141,6 @@ You can see more in the `persistence` chapter.
If you have your `Document`s defined you can very easily create a faceted search class to simplify searching and filtering.
-::::{note}
-This feature is experimental and may be subject to change.
-
-::::
-
-
```python
from elasticsearch.dsl import FacetedSearch, TermsFacet, DateHistogramFacet
@@ -208,11 +202,12 @@ Using the DSL, we can now express this query as such:
```python
from elasticsearch import Elasticsearch
from elasticsearch.dsl import Search, UpdateByQuery
+from elasticsearch.dsl.query import Match
client = Elasticsearch()
ubq = UpdateByQuery(using=client, index="my-index") \
- .query("match", title="python") \
- .exclude("match", description="beta") \
+ .query(Match("title", "python")) \
+ .exclude(Match("description", "beta")) \
.script(source="ctx._source.likes++", lang="painless")
response = ubq.execute()
@@ -232,7 +227,7 @@ body = {...} # insert complicated query here
s = Search.from_dict(body)
# Add some filters, aggregations, queries, ...
-s.filter("term", tags="python")
+s.filter(query.Term("tags", "python"))
# Convert back to dict to plug back into existing code
body = s.to_dict()
diff --git a/docs/reference/elasticsearch-dsl.md b/docs/reference/elasticsearch-dsl.md
index 4030e232d..ad72cb1fe 100644
--- a/docs/reference/elasticsearch-dsl.md
+++ b/docs/reference/elasticsearch-dsl.md
@@ -9,11 +9,12 @@ Elasticsearch DSL is a module of the official Python client that aims to help wi
```python
from elasticsearch.dsl import Search
+from elasticsearch.dsl.query import Match, Term
s = Search(index="my-index") \
- .filter("term", category="search") \
- .query("match", title="python") \
- .exclude("match", description="beta")
+ .query(Match("title", "python")) \
+ .filter(Term("category", "search")) \
+ .exclude(Match("description", "beta"))
for hit in s:
print(hit.title)
```
@@ -22,12 +23,13 @@ Or with asynchronous Python:
```python
from elasticsearch.dsl import AsyncSearch
+from elasticsearch.dsl.query import Match, Term
async def run_query():
s = AsyncSearch(index="my-index") \
- .filter("term", category="search") \
- .query("match", title="python") \
- .exclude("match", description="beta")
+ .query(Match("title", "python")) \
+ .filter(Term("category", "search")) \
+ .exclude(Match("description", "beta"))
async for hit in s:
print(hit.title)
```
diff --git a/docs/reference/toc.yml b/docs/reference/toc.yml
index abb74bc42..0ff68225e 100644
--- a/docs/reference/toc.yml
+++ b/docs/reference/toc.yml
@@ -16,4 +16,5 @@ toc:
- file: dsl_tutorials.md
- file: dsl_how_to_guides.md
- file: dsl_examples.md
+ - file: dsl_migrating.md
- file: client-helpers.md
diff --git a/elasticsearch/dsl/search_base.py b/elasticsearch/dsl/search_base.py
index c513fc78d..cd690ddae 100644
--- a/elasticsearch/dsl/search_base.py
+++ b/elasticsearch/dsl/search_base.py
@@ -72,6 +72,9 @@ def __nonzero__(self) -> bool:
__bool__ = __nonzero__
def __call__(self, *args: Any, **kwargs: Any) -> _S:
+ """
+ Add a query.
+ """
s = self._search._clone()
# we cannot use self._proxied since we just cloned self._search and
@@ -354,18 +357,22 @@ class SearchBase(Request[_R]):
post_filter = ProxyDescriptor[Self]("post_filter")
_response: Response[_R]
- def __init__(self, **kwargs: Any):
+ def __init__(
+ self,
+ using: AnyUsingType = "default",
+ index: Optional[Union[str, List[str]]] = None,
+ **kwargs: Any,
+ ):
"""
Search request to elasticsearch.
:arg using: `Elasticsearch` instance to use
:arg index: limit the search to index
- :arg doc_type: only query this type.
All the parameters supplied (or omitted) at creation type can be later
overridden by methods (`using`, `index` and `doc_type` respectively).
"""
- super().__init__(**kwargs)
+ super().__init__(using=using, index=index, **kwargs)
self.aggs = AggsProxy[_R](self)
self._sort: List[Union[str, Dict[str, Dict[str, str]]]] = []
@@ -383,9 +390,15 @@ def __init__(self, **kwargs: Any):
self._post_filter_proxy = QueryProxy(self, "post_filter")
def filter(self, *args: Any, **kwargs: Any) -> Self:
+ """
+ Add a query in filter context.
+ """
return self.query(Bool(filter=[Q(*args, **kwargs)]))
def exclude(self, *args: Any, **kwargs: Any) -> Self:
+ """
+ Add a negative query in filter context.
+ """
return self.query(Bool(filter=[~Q(*args, **kwargs)]))
def __getitem__(self, n: Union[int, slice]) -> Self:
From 5702bde0348f732f43ad6a70ebc99dceb1667ff4 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 31 Mar 2025 16:32:15 +0100
Subject: [PATCH 08/57] Remove unneded nonlocal and global declarations (#2866)
(#2868)
(cherry picked from commit 83025a601ce112e6045abe1b5d84cfbaed722b3f)
Co-authored-by: Miguel Grinberg
---
elasticsearch/_async/client/_base.py | 1 -
elasticsearch/_async/helpers.py | 1 -
elasticsearch/_sync/client/_base.py | 1 -
elasticsearch/_sync/client/utils.py | 3 ---
test_elasticsearch/test_server/test_rest_api_spec.py | 4 +---
utils/build-dists.py | 1 -
6 files changed, 1 insertion(+), 10 deletions(-)
diff --git a/elasticsearch/_async/client/_base.py b/elasticsearch/_async/client/_base.py
index dd0b0f44e..cc090671c 100644
--- a/elasticsearch/_async/client/_base.py
+++ b/elasticsearch/_async/client/_base.py
@@ -298,7 +298,6 @@ async def _perform_request(
def mimetype_header_to_compat(header: str) -> None:
# Converts all parts of a Accept/Content-Type headers
# from application/X -> application/vnd.elasticsearch+X
- nonlocal request_headers
mimetype = request_headers.get(header, None)
if mimetype:
request_headers[header] = _COMPAT_MIMETYPE_RE.sub(
diff --git a/elasticsearch/_async/helpers.py b/elasticsearch/_async/helpers.py
index 4c53f0bbe..e4d5e6bc5 100644
--- a/elasticsearch/_async/helpers.py
+++ b/elasticsearch/_async/helpers.py
@@ -136,7 +136,6 @@ def aiter(x: Union[Iterable[T], AsyncIterable[T]]) -> AsyncIterator[T]:
return x.__aiter__()
async def f() -> AsyncIterable[T]:
- nonlocal x
ix: Iterable[T] = x
for item in ix:
yield item
diff --git a/elasticsearch/_sync/client/_base.py b/elasticsearch/_sync/client/_base.py
index 8929b1db7..868b71073 100644
--- a/elasticsearch/_sync/client/_base.py
+++ b/elasticsearch/_sync/client/_base.py
@@ -298,7 +298,6 @@ def _perform_request(
def mimetype_header_to_compat(header: str) -> None:
# Converts all parts of a Accept/Content-Type headers
# from application/X -> application/vnd.elasticsearch+X
- nonlocal request_headers
mimetype = request_headers.get(header, None)
if mimetype:
request_headers[header] = _COMPAT_MIMETYPE_RE.sub(
diff --git a/elasticsearch/_sync/client/utils.py b/elasticsearch/_sync/client/utils.py
index 45f33fc6e..48ebcb217 100644
--- a/elasticsearch/_sync/client/utils.py
+++ b/elasticsearch/_sync/client/utils.py
@@ -134,7 +134,6 @@ def client_node_configs(
def apply_node_options(node_config: NodeConfig) -> NodeConfig:
"""Needs special handling of headers since .replace() wipes out existing headers"""
- nonlocal node_options
headers = node_config.headers.copy() # type: ignore[attr-defined]
headers_to_add = node_options.pop("headers", ())
@@ -306,8 +305,6 @@ def _rewrite_parameters(
def wrapper(api: F) -> F:
@wraps(api)
def wrapped(*args: Any, **kwargs: Any) -> Any:
- nonlocal api, body_name, body_fields
-
# Let's give a nicer error message when users pass positional arguments.
if len(args) >= 2:
raise TypeError(
diff --git a/test_elasticsearch/test_server/test_rest_api_spec.py b/test_elasticsearch/test_server/test_rest_api_spec.py
index 0b602684a..a84f0822a 100644
--- a/test_elasticsearch/test_server/test_rest_api_spec.py
+++ b/test_elasticsearch/test_server/test_rest_api_spec.py
@@ -280,8 +280,6 @@ def run_catch(self, catch, exception):
self.last_response = exception.body
def run_skip(self, skip):
- global IMPLEMENTED_FEATURES
-
if "features" in skip:
features = skip["features"]
if not isinstance(features, (tuple, list)):
@@ -437,7 +435,7 @@ def _lookup(self, path):
return value
def _feature_enabled(self, name):
- global XPACK_FEATURES, IMPLEMENTED_FEATURES
+ global XPACK_FEATURES
if XPACK_FEATURES is None:
try:
xinfo = self.client.xpack.info()
diff --git a/utils/build-dists.py b/utils/build-dists.py
index ec8083103..d67d6053a 100644
--- a/utils/build-dists.py
+++ b/utils/build-dists.py
@@ -42,7 +42,6 @@ def set_tmp_dir():
def run(*argv, expect_exit_code=0):
- global tmp_dir
try:
prev_dir = os.getcwd()
if tmp_dir is None:
From 01893c88ed6440d0ad10b53a3ded8c04d063833e Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 1 Apr 2025 09:59:41 +0100
Subject: [PATCH 09/57] [docs] Add param notes to DSL search.delete
documentation, fix broken links (#2861) (#2869)
* Add param notes to DSL search.delete documentation, fix broken links
The preferred way of passing parameters to the DSL `Search.delete` appears to be calling `Search.params` first,
but this is only ever discussed in GitHub issues like
elastic/elasticsearch-dsl-py#1115
and elastic/elasticsearch-dsl-py#1395.
To help anyone else who has stumbled across this, I added a note about this to the documentation.
I also went ahead and updated the links for the `Search.scan` and `FacetedSearch.params`
methods to the most recent versions since they were 404ing.
* make sync and async changes the same
---------
Co-authored-by: Luna Lucadou
Co-authored-by: Miguel Grinberg
(cherry picked from commit b6d1211cfb04825eb00f9d756738af3258eba199)
Co-authored-by: Luna Lucadou <22415965+lunalucadou@users.noreply.github.com>
---
docs/reference/dsl_how_to_guides.md | 9 +++++++++
elasticsearch/dsl/_async/search.py | 10 +++++++---
elasticsearch/dsl/_sync/search.py | 10 +++++++---
elasticsearch/dsl/faceted_search_base.py | 2 +-
4 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/docs/reference/dsl_how_to_guides.md b/docs/reference/dsl_how_to_guides.md
index 93dc8d9a1..ce128528a 100644
--- a/docs/reference/dsl_how_to_guides.md
+++ b/docs/reference/dsl_how_to_guides.md
@@ -84,6 +84,15 @@ s = Search(index='i').query(Match("title", "python"))
response = s.delete()
```
+To pass [deletion parameters](https://elasticsearch-py.readthedocs.io/en/latest/api/elasticsearch.html#elasticsearch.Elasticsearch.delete_by_query)
+in your query, you can add them by calling ``params`` on the ``Search`` object before ``delete`` like this:
+
+```python
+s = Search(index='i').query("match", title="python")
+s = s.params(ignore_unavailable=False, wait_for_completion=True)
+response = s.delete()
+```
+
#### Queries [_queries]
diff --git a/elasticsearch/dsl/_async/search.py b/elasticsearch/dsl/_async/search.py
index 42eb142fd..2ea277a07 100644
--- a/elasticsearch/dsl/_async/search.py
+++ b/elasticsearch/dsl/_async/search.py
@@ -107,9 +107,9 @@ async def scan(self) -> AsyncIterator[_R]:
Turn the search into a scan search and return a generator that will
iterate over all the documents matching the query.
- Use ``params`` method to specify any additional arguments you with to
+ Use the ``params`` method to specify any additional arguments you wish to
pass to the underlying ``scan`` helper from ``elasticsearch-py`` -
- https://elasticsearch-py.readthedocs.io/en/master/helpers.html#elasticsearch.helpers.scan
+ https://elasticsearch-py.readthedocs.io/en/latest/helpers.html#scan
The ``iterate()`` method should be preferred, as it provides similar
functionality using an Elasticsearch point in time.
@@ -123,7 +123,11 @@ async def scan(self) -> AsyncIterator[_R]:
async def delete(self) -> AttrDict[Any]:
"""
- delete() executes the query by delegating to delete_by_query()
+ ``delete()`` executes the query by delegating to ``delete_by_query()``.
+
+ Use the ``params`` method to specify any additional arguments you wish to
+ pass to the underlying ``delete_by_query`` helper from ``elasticsearch-py`` -
+ https://elasticsearch-py.readthedocs.io/en/latest/api/elasticsearch.html#elasticsearch.Elasticsearch.delete_by_query
"""
es = get_connection(self._using)
diff --git a/elasticsearch/dsl/_sync/search.py b/elasticsearch/dsl/_sync/search.py
index ae826a12f..4dfbdb92b 100644
--- a/elasticsearch/dsl/_sync/search.py
+++ b/elasticsearch/dsl/_sync/search.py
@@ -104,9 +104,9 @@ def scan(self) -> Iterator[_R]:
Turn the search into a scan search and return a generator that will
iterate over all the documents matching the query.
- Use ``params`` method to specify any additional arguments you with to
+ Use the ``params`` method to specify any additional arguments you wish to
pass to the underlying ``scan`` helper from ``elasticsearch-py`` -
- https://elasticsearch-py.readthedocs.io/en/master/helpers.html#elasticsearch.helpers.scan
+ https://elasticsearch-py.readthedocs.io/en/latest/helpers.html#scan
The ``iterate()`` method should be preferred, as it provides similar
functionality using an Elasticsearch point in time.
@@ -118,7 +118,11 @@ def scan(self) -> Iterator[_R]:
def delete(self) -> AttrDict[Any]:
"""
- delete() executes the query by delegating to delete_by_query()
+ ``delete()`` executes the query by delegating to ``delete_by_query()``.
+
+ Use the ``params`` method to specify any additional arguments you wish to
+ pass to the underlying ``delete_by_query`` helper from ``elasticsearch-py`` -
+ https://elasticsearch-py.readthedocs.io/en/latest/api/elasticsearch.html#elasticsearch.Elasticsearch.delete_by_query
"""
es = get_connection(self._using)
diff --git a/elasticsearch/dsl/faceted_search_base.py b/elasticsearch/dsl/faceted_search_base.py
index 5caa041bf..b58f23dca 100644
--- a/elasticsearch/dsl/faceted_search_base.py
+++ b/elasticsearch/dsl/faceted_search_base.py
@@ -469,7 +469,7 @@ def params(self, **kwargs: Any) -> None:
"""
Specify query params to be used when executing the search. All the
keyword arguments will override the current values. See
- https://elasticsearch-py.readthedocs.io/en/master/api.html#elasticsearch.Elasticsearch.search
+ https://elasticsearch-py.readthedocs.io/en/latest/api/elasticsearch.html#elasticsearch.Elasticsearch.search
for all available parameters.
"""
self._s = self._s.params(**kwargs)
From 43ce0dc4e1edf4b150ca27d04d4f412dbf71ea89 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 1 Apr 2025 10:32:39 +0100
Subject: [PATCH 10/57] Handle new aggregation range types Pythoncally (#2860)
(#2865)
(cherry picked from commit a224f49cef40e55ea847c4831083ce6648e618d3)
Co-authored-by: Miguel Grinberg
---
elasticsearch/dsl/aggs.py | 13 +-
elasticsearch/dsl/faceted_search_base.py | 6 +-
elasticsearch/dsl/field.py | 157 ++++++++++++++++++++++-
elasticsearch/dsl/query.py | 8 +-
elasticsearch/dsl/types.py | 120 ++++++-----------
elasticsearch/dsl/wrappers.py | 25 ++++
utils/dsl-generator.py | 35 +++--
utils/templates/aggs.py.tpl | 1 +
8 files changed, 269 insertions(+), 96 deletions(-)
diff --git a/elasticsearch/dsl/aggs.py b/elasticsearch/dsl/aggs.py
index ba5150803..a20373163 100644
--- a/elasticsearch/dsl/aggs.py
+++ b/elasticsearch/dsl/aggs.py
@@ -35,6 +35,7 @@
from elastic_transport.client_utils import DEFAULT
+from . import wrappers
from .query import Query
from .response.aggs import AggResponse, BucketData, FieldBucketData, TopHitsData
from .utils import _R, AttrDict, DslBase
@@ -761,7 +762,7 @@ def __init__(
*,
after: Union[
Mapping[
- Union[str, "InstrumentedField"], Union[int, float, str, bool, None, Any]
+ Union[str, "InstrumentedField"], Union[int, float, str, bool, None]
],
"DefaultType",
] = DEFAULT,
@@ -958,7 +959,7 @@ def __init__(
format: Union[str, "DefaultType"] = DEFAULT,
missing: Union[str, int, float, bool, "DefaultType"] = DEFAULT,
ranges: Union[
- Sequence["types.DateRangeExpression"],
+ Sequence["wrappers.AggregationRange"],
Sequence[Dict[str, Any]],
"DefaultType",
] = DEFAULT,
@@ -1347,7 +1348,9 @@ def __init__(
"DefaultType",
] = DEFAULT,
ranges: Union[
- Sequence["types.AggregationRange"], Sequence[Dict[str, Any]], "DefaultType"
+ Sequence["wrappers.AggregationRange"],
+ Sequence[Dict[str, Any]],
+ "DefaultType",
] = DEFAULT,
unit: Union[
Literal["in", "ft", "yd", "mi", "nmi", "km", "m", "cm", "mm"], "DefaultType"
@@ -2657,7 +2660,9 @@ def __init__(
field: Union[str, "InstrumentedField", "DefaultType"] = DEFAULT,
missing: Union[int, "DefaultType"] = DEFAULT,
ranges: Union[
- Sequence["types.AggregationRange"], Sequence[Dict[str, Any]], "DefaultType"
+ Sequence["wrappers.AggregationRange"],
+ Sequence[Dict[str, Any]],
+ "DefaultType",
] = DEFAULT,
script: Union["types.Script", Dict[str, Any], "DefaultType"] = DEFAULT,
keyed: Union[bool, "DefaultType"] = DEFAULT,
diff --git a/elasticsearch/dsl/faceted_search_base.py b/elasticsearch/dsl/faceted_search_base.py
index b58f23dca..c70a5db0e 100644
--- a/elasticsearch/dsl/faceted_search_base.py
+++ b/elasticsearch/dsl/faceted_search_base.py
@@ -42,7 +42,7 @@
from .response.aggs import BucketData
from .search_base import SearchBase
-FilterValueType = Union[str, datetime, Sequence[str]]
+FilterValueType = Union[str, int, float, bool]
__all__ = [
"FacetedSearchBase",
@@ -396,10 +396,10 @@ def add_filter(
]
# remember the filter values for use in FacetedResponse
- self.filter_values[name] = filter_values # type: ignore[assignment]
+ self.filter_values[name] = filter_values
# get the filter from the facet
- f = self.facets[name].add_filter(filter_values) # type: ignore[arg-type]
+ f = self.facets[name].add_filter(filter_values)
if f is None:
return
diff --git a/elasticsearch/dsl/field.py b/elasticsearch/dsl/field.py
index 7fcc9ada5..726fbe358 100644
--- a/elasticsearch/dsl/field.py
+++ b/elasticsearch/dsl/field.py
@@ -437,7 +437,9 @@ def __init__(
doc_class: Union[Type["InnerDoc"], "DefaultType"] = DEFAULT,
*args: Any,
enabled: Union[bool, "DefaultType"] = DEFAULT,
- subobjects: Union[bool, "DefaultType"] = DEFAULT,
+ subobjects: Union[
+ Literal["true", "false", "auto"], bool, "DefaultType"
+ ] = DEFAULT,
copy_to: Union[
Union[str, "InstrumentedField"],
Sequence[Union[str, "InstrumentedField"]],
@@ -762,6 +764,11 @@ class Boolean(Field):
:arg fielddata:
:arg index:
:arg null_value:
+ :arg ignore_malformed:
+ :arg script:
+ :arg on_script_error:
+ :arg time_series_dimension: For internal use by Elastic only. Marks
+ the field as a time series dimension. Defaults to false.
:arg doc_values:
:arg copy_to:
:arg store:
@@ -789,6 +796,10 @@ def __init__(
] = DEFAULT,
index: Union[bool, "DefaultType"] = DEFAULT,
null_value: Union[bool, "DefaultType"] = DEFAULT,
+ ignore_malformed: Union[bool, "DefaultType"] = DEFAULT,
+ script: Union["types.Script", Dict[str, Any], "DefaultType"] = DEFAULT,
+ on_script_error: Union[Literal["fail", "continue"], "DefaultType"] = DEFAULT,
+ time_series_dimension: Union[bool, "DefaultType"] = DEFAULT,
doc_values: Union[bool, "DefaultType"] = DEFAULT,
copy_to: Union[
Union[str, "InstrumentedField"],
@@ -816,6 +827,14 @@ def __init__(
kwargs["index"] = index
if null_value is not DEFAULT:
kwargs["null_value"] = null_value
+ if ignore_malformed is not DEFAULT:
+ kwargs["ignore_malformed"] = ignore_malformed
+ if script is not DEFAULT:
+ kwargs["script"] = script
+ if on_script_error is not DEFAULT:
+ kwargs["on_script_error"] = on_script_error
+ if time_series_dimension is not DEFAULT:
+ kwargs["time_series_dimension"] = time_series_dimension
if doc_values is not DEFAULT:
kwargs["doc_values"] = doc_values
if copy_to is not DEFAULT:
@@ -1092,6 +1111,56 @@ def __init__(
super().__init__(*args, **kwargs)
+class CountedKeyword(Field):
+ """
+ :arg index:
+ :arg meta: Metadata about the field.
+ :arg properties:
+ :arg ignore_above:
+ :arg dynamic:
+ :arg fields:
+ :arg synthetic_source_keep:
+ """
+
+ name = "counted_keyword"
+ _param_defs = {
+ "properties": {"type": "field", "hash": True},
+ "fields": {"type": "field", "hash": True},
+ }
+
+ def __init__(
+ self,
+ *args: Any,
+ index: Union[bool, "DefaultType"] = DEFAULT,
+ meta: Union[Mapping[str, str], "DefaultType"] = DEFAULT,
+ properties: Union[Mapping[str, Field], "DefaultType"] = DEFAULT,
+ ignore_above: Union[int, "DefaultType"] = DEFAULT,
+ dynamic: Union[
+ Literal["strict", "runtime", "true", "false"], bool, "DefaultType"
+ ] = DEFAULT,
+ fields: Union[Mapping[str, Field], "DefaultType"] = DEFAULT,
+ synthetic_source_keep: Union[
+ Literal["none", "arrays", "all"], "DefaultType"
+ ] = DEFAULT,
+ **kwargs: Any,
+ ):
+ if index is not DEFAULT:
+ kwargs["index"] = index
+ if meta is not DEFAULT:
+ kwargs["meta"] = meta
+ if properties is not DEFAULT:
+ kwargs["properties"] = properties
+ if ignore_above is not DEFAULT:
+ kwargs["ignore_above"] = ignore_above
+ if dynamic is not DEFAULT:
+ kwargs["dynamic"] = dynamic
+ if fields is not DEFAULT:
+ kwargs["fields"] = fields
+ if synthetic_source_keep is not DEFAULT:
+ kwargs["synthetic_source_keep"] = synthetic_source_keep
+ super().__init__(*args, **kwargs)
+
+
class Date(Field):
"""
:arg default_timezone: timezone that will be automatically used for tz-naive values
@@ -1101,6 +1170,8 @@ class Date(Field):
:arg format:
:arg ignore_malformed:
:arg index:
+ :arg script:
+ :arg on_script_error:
:arg null_value:
:arg precision_step:
:arg locale:
@@ -1133,6 +1204,8 @@ def __init__(
format: Union[str, "DefaultType"] = DEFAULT,
ignore_malformed: Union[bool, "DefaultType"] = DEFAULT,
index: Union[bool, "DefaultType"] = DEFAULT,
+ script: Union["types.Script", Dict[str, Any], "DefaultType"] = DEFAULT,
+ on_script_error: Union[Literal["fail", "continue"], "DefaultType"] = DEFAULT,
null_value: Any = DEFAULT,
precision_step: Union[int, "DefaultType"] = DEFAULT,
locale: Union[str, "DefaultType"] = DEFAULT,
@@ -1165,6 +1238,10 @@ def __init__(
kwargs["ignore_malformed"] = ignore_malformed
if index is not DEFAULT:
kwargs["index"] = index
+ if script is not DEFAULT:
+ kwargs["script"] = script
+ if on_script_error is not DEFAULT:
+ kwargs["on_script_error"] = on_script_error
if null_value is not DEFAULT:
kwargs["null_value"] = null_value
if precision_step is not DEFAULT:
@@ -1229,6 +1306,8 @@ class DateNanos(Field):
:arg format:
:arg ignore_malformed:
:arg index:
+ :arg script:
+ :arg on_script_error:
:arg null_value:
:arg precision_step:
:arg doc_values:
@@ -1255,6 +1334,8 @@ def __init__(
format: Union[str, "DefaultType"] = DEFAULT,
ignore_malformed: Union[bool, "DefaultType"] = DEFAULT,
index: Union[bool, "DefaultType"] = DEFAULT,
+ script: Union["types.Script", Dict[str, Any], "DefaultType"] = DEFAULT,
+ on_script_error: Union[Literal["fail", "continue"], "DefaultType"] = DEFAULT,
null_value: Any = DEFAULT,
precision_step: Union[int, "DefaultType"] = DEFAULT,
doc_values: Union[bool, "DefaultType"] = DEFAULT,
@@ -1284,6 +1365,10 @@ def __init__(
kwargs["ignore_malformed"] = ignore_malformed
if index is not DEFAULT:
kwargs["index"] = index
+ if script is not DEFAULT:
+ kwargs["script"] = script
+ if on_script_error is not DEFAULT:
+ kwargs["on_script_error"] = on_script_error
if null_value is not DEFAULT:
kwargs["null_value"] = null_value
if precision_step is not DEFAULT:
@@ -3068,6 +3153,76 @@ def __init__(
super().__init__(*args, **kwargs)
+class Passthrough(Field):
+ """
+ :arg enabled:
+ :arg priority:
+ :arg time_series_dimension:
+ :arg copy_to:
+ :arg store:
+ :arg meta: Metadata about the field.
+ :arg properties:
+ :arg ignore_above:
+ :arg dynamic:
+ :arg fields:
+ :arg synthetic_source_keep:
+ """
+
+ name = "passthrough"
+ _param_defs = {
+ "properties": {"type": "field", "hash": True},
+ "fields": {"type": "field", "hash": True},
+ }
+
+ def __init__(
+ self,
+ *args: Any,
+ enabled: Union[bool, "DefaultType"] = DEFAULT,
+ priority: Union[int, "DefaultType"] = DEFAULT,
+ time_series_dimension: Union[bool, "DefaultType"] = DEFAULT,
+ copy_to: Union[
+ Union[str, "InstrumentedField"],
+ Sequence[Union[str, "InstrumentedField"]],
+ "DefaultType",
+ ] = DEFAULT,
+ store: Union[bool, "DefaultType"] = DEFAULT,
+ meta: Union[Mapping[str, str], "DefaultType"] = DEFAULT,
+ properties: Union[Mapping[str, Field], "DefaultType"] = DEFAULT,
+ ignore_above: Union[int, "DefaultType"] = DEFAULT,
+ dynamic: Union[
+ Literal["strict", "runtime", "true", "false"], bool, "DefaultType"
+ ] = DEFAULT,
+ fields: Union[Mapping[str, Field], "DefaultType"] = DEFAULT,
+ synthetic_source_keep: Union[
+ Literal["none", "arrays", "all"], "DefaultType"
+ ] = DEFAULT,
+ **kwargs: Any,
+ ):
+ if enabled is not DEFAULT:
+ kwargs["enabled"] = enabled
+ if priority is not DEFAULT:
+ kwargs["priority"] = priority
+ if time_series_dimension is not DEFAULT:
+ kwargs["time_series_dimension"] = time_series_dimension
+ if copy_to is not DEFAULT:
+ kwargs["copy_to"] = str(copy_to)
+ if store is not DEFAULT:
+ kwargs["store"] = store
+ if meta is not DEFAULT:
+ kwargs["meta"] = meta
+ if properties is not DEFAULT:
+ kwargs["properties"] = properties
+ if ignore_above is not DEFAULT:
+ kwargs["ignore_above"] = ignore_above
+ if dynamic is not DEFAULT:
+ kwargs["dynamic"] = dynamic
+ if fields is not DEFAULT:
+ kwargs["fields"] = fields
+ if synthetic_source_keep is not DEFAULT:
+ kwargs["synthetic_source_keep"] = synthetic_source_keep
+ super().__init__(*args, **kwargs)
+
+
class Percolator(Field):
"""
:arg meta: Metadata about the field.
diff --git a/elasticsearch/dsl/query.py b/elasticsearch/dsl/query.py
index 6e87f926c..1282d3b02 100644
--- a/elasticsearch/dsl/query.py
+++ b/elasticsearch/dsl/query.py
@@ -1083,6 +1083,8 @@ class Knn(Query):
:arg filter: Filters for the kNN search query
:arg similarity: The minimum similarity for a vector to be considered
a match
+ :arg rescore_vector: Apply oversampling and rescoring to quantized
+ vectors *
:arg boost: Floating point number used to decrease or increase the
relevance scores of the query. Boost values are relative to the
default value of 1.0. A boost value between 0 and 1.0 decreases
@@ -1108,6 +1110,9 @@ def __init__(
k: Union[int, "DefaultType"] = DEFAULT,
filter: Union[Query, Sequence[Query], "DefaultType"] = DEFAULT,
similarity: Union[float, "DefaultType"] = DEFAULT,
+ rescore_vector: Union[
+ "types.RescoreVector", Dict[str, Any], "DefaultType"
+ ] = DEFAULT,
boost: Union[float, "DefaultType"] = DEFAULT,
_name: Union[str, "DefaultType"] = DEFAULT,
**kwargs: Any,
@@ -1120,6 +1125,7 @@ def __init__(
k=k,
filter=filter,
similarity=similarity,
+ rescore_vector=rescore_vector,
boost=boost,
_name=_name,
**kwargs,
@@ -2650,7 +2656,7 @@ def __init__(
self,
_field: Union[str, "InstrumentedField", "DefaultType"] = DEFAULT,
_value: Union[
- Sequence[Union[int, float, str, bool, None, Any]],
+ Sequence[Union[int, float, str, bool, None]],
"types.TermsLookup",
Dict[str, Any],
"DefaultType",
diff --git a/elasticsearch/dsl/types.py b/elasticsearch/dsl/types.py
index 7474769c6..772e596cd 100644
--- a/elasticsearch/dsl/types.py
+++ b/elasticsearch/dsl/types.py
@@ -26,34 +26,6 @@
PipeSeparatedFlags = str
-class AggregationRange(AttrDict[Any]):
- """
- :arg from: Start of the range (inclusive).
- :arg key: Custom key to return the range with.
- :arg to: End of the range (exclusive).
- """
-
- from_: Union[float, None, DefaultType]
- key: Union[str, DefaultType]
- to: Union[float, None, DefaultType]
-
- def __init__(
- self,
- *,
- from_: Union[float, None, DefaultType] = DEFAULT,
- key: Union[str, DefaultType] = DEFAULT,
- to: Union[float, None, DefaultType] = DEFAULT,
- **kwargs: Any,
- ):
- if from_ is not DEFAULT:
- kwargs["from_"] = from_
- if key is not DEFAULT:
- kwargs["key"] = key
- if to is not DEFAULT:
- kwargs["to"] = to
- super().__init__(kwargs)
-
-
class BucketCorrelationFunction(AttrDict[Any]):
"""
:arg count_correlation: (required) The configuration to calculate a
@@ -334,34 +306,6 @@ def __init__(
super().__init__(kwargs)
-class DateRangeExpression(AttrDict[Any]):
- """
- :arg from: Start of the range (inclusive).
- :arg key: Custom key to return the range with.
- :arg to: End of the range (exclusive).
- """
-
- from_: Union[str, float, DefaultType]
- key: Union[str, DefaultType]
- to: Union[str, float, DefaultType]
-
- def __init__(
- self,
- *,
- from_: Union[str, float, DefaultType] = DEFAULT,
- key: Union[str, DefaultType] = DEFAULT,
- to: Union[str, float, DefaultType] = DEFAULT,
- **kwargs: Any,
- ):
- if from_ is not DEFAULT:
- kwargs["from_"] = from_
- if key is not DEFAULT:
- kwargs["key"] = key
- if to is not DEFAULT:
- kwargs["to"] = to
- super().__init__(kwargs)
-
-
class DenseVectorIndexOptions(AttrDict[Any]):
"""
:arg type: (required) The type of kNN algorithm to use.
@@ -591,6 +535,7 @@ class FieldSort(AttrDict[Any]):
"completion",
"nested",
"object",
+ "passthrough",
"version",
"murmur3",
"token_count",
@@ -617,6 +562,7 @@ class FieldSort(AttrDict[Any]):
"shape",
"histogram",
"constant_keyword",
+ "counted_keyword",
"aggregate_metric_double",
"dense_vector",
"semantic_text",
@@ -654,6 +600,7 @@ def __init__(
"completion",
"nested",
"object",
+ "passthrough",
"version",
"murmur3",
"token_count",
@@ -680,6 +627,7 @@ def __init__(
"shape",
"histogram",
"constant_keyword",
+ "counted_keyword",
"aggregate_metric_double",
"dense_vector",
"semantic_text",
@@ -2625,7 +2573,7 @@ class PercentageScoreHeuristic(AttrDict[Any]):
class PinnedDoc(AttrDict[Any]):
"""
:arg _id: (required) The unique document ID.
- :arg _index: (required) The index that contains the document.
+ :arg _index: The index that contains the document.
"""
_id: Union[str, DefaultType]
@@ -2850,6 +2798,22 @@ def __init__(
super().__init__(kwargs)
+class RescoreVector(AttrDict[Any]):
+ """
+ :arg oversample: (required) Applies the specified oversample factor to
+ k on the approximate kNN search
+ """
+
+ oversample: Union[float, DefaultType]
+
+ def __init__(
+ self, *, oversample: Union[float, DefaultType] = DEFAULT, **kwargs: Any
+ ):
+ if oversample is not DEFAULT:
+ kwargs["oversample"] = oversample
+ super().__init__(kwargs)
+
+
class ScoreSort(AttrDict[Any]):
"""
:arg order:
@@ -2880,7 +2844,7 @@ class Script(AttrDict[Any]):
:arg options:
"""
- source: Union[str, DefaultType]
+ source: Union[str, Dict[str, Any], DefaultType]
id: Union[str, DefaultType]
params: Union[Mapping[str, Any], DefaultType]
lang: Union[Literal["painless", "expression", "mustache", "java"], DefaultType]
@@ -2889,7 +2853,7 @@ class Script(AttrDict[Any]):
def __init__(
self,
*,
- source: Union[str, DefaultType] = DEFAULT,
+ source: Union[str, Dict[str, Any], DefaultType] = DEFAULT,
id: Union[str, DefaultType] = DEFAULT,
params: Union[Mapping[str, Any], DefaultType] = DEFAULT,
lang: Union[
@@ -3488,14 +3452,14 @@ class SpanTermQuery(AttrDict[Any]):
:arg _name:
"""
- value: Union[str, DefaultType]
+ value: Union[int, float, str, bool, None, DefaultType]
boost: Union[float, DefaultType]
_name: Union[str, DefaultType]
def __init__(
self,
*,
- value: Union[str, DefaultType] = DEFAULT,
+ value: Union[int, float, str, bool, None, DefaultType] = DEFAULT,
boost: Union[float, DefaultType] = DEFAULT,
_name: Union[str, DefaultType] = DEFAULT,
**kwargs: Any,
@@ -3613,7 +3577,7 @@ class TermQuery(AttrDict[Any]):
:arg _name:
"""
- value: Union[int, float, str, bool, None, Any, DefaultType]
+ value: Union[int, float, str, bool, None, DefaultType]
case_insensitive: Union[bool, DefaultType]
boost: Union[float, DefaultType]
_name: Union[str, DefaultType]
@@ -3621,7 +3585,7 @@ class TermQuery(AttrDict[Any]):
def __init__(
self,
*,
- value: Union[int, float, str, bool, None, Any, DefaultType] = DEFAULT,
+ value: Union[int, float, str, bool, None, DefaultType] = DEFAULT,
case_insensitive: Union[bool, DefaultType] = DEFAULT,
boost: Union[float, DefaultType] = DEFAULT,
_name: Union[str, DefaultType] = DEFAULT,
@@ -3712,7 +3676,7 @@ class TermsSetQuery(AttrDict[Any]):
:arg _name:
"""
- terms: Union[Sequence[str], DefaultType]
+ terms: Union[Sequence[Union[int, float, str, bool, None]], DefaultType]
minimum_should_match: Union[int, str, DefaultType]
minimum_should_match_field: Union[str, InstrumentedField, DefaultType]
minimum_should_match_script: Union["Script", Dict[str, Any], DefaultType]
@@ -3722,7 +3686,9 @@ class TermsSetQuery(AttrDict[Any]):
def __init__(
self,
*,
- terms: Union[Sequence[str], DefaultType] = DEFAULT,
+ terms: Union[
+ Sequence[Union[int, float, str, bool, None]], DefaultType
+ ] = DEFAULT,
minimum_should_match: Union[int, str, DefaultType] = DEFAULT,
minimum_should_match_field: Union[
str, InstrumentedField, DefaultType
@@ -4544,7 +4510,7 @@ class CompositeAggregate(AttrDict[Any]):
:arg meta:
"""
- after_key: Mapping[str, Union[int, float, str, bool, None, Any]]
+ after_key: Mapping[str, Union[int, float, str, bool, None]]
buckets: Sequence["CompositeBucket"]
meta: Mapping[str, Any]
@@ -4559,7 +4525,7 @@ class CompositeBucket(AttrDict[Any]):
:arg doc_count: (required)
"""
- key: Mapping[str, Union[int, float, str, bool, None, Any]]
+ key: Mapping[str, Union[int, float, str, bool, None]]
doc_count: int
@@ -5235,9 +5201,7 @@ class Hit(AttrDict[Any]):
matched_queries: Union[Sequence[str], Mapping[str, float]]
nested: "NestedIdentity"
ignored: Sequence[str]
- ignored_field_values: Mapping[
- str, Sequence[Union[int, float, str, bool, None, Any]]
- ]
+ ignored_field_values: Mapping[str, Sequence[Any]]
shard: str
node: str
routing: str
@@ -5246,7 +5210,7 @@ class Hit(AttrDict[Any]):
seq_no: int
primary_term: int
version: int
- sort: Sequence[Union[int, float, str, bool, None, Any]]
+ sort: Sequence[Union[int, float, str, bool, None]]
class HitsMetadata(AttrDict[Any]):
@@ -5271,7 +5235,7 @@ class InferenceAggregate(AttrDict[Any]):
:arg meta:
"""
- value: Union[int, float, str, bool, None, Any]
+ value: Union[int, float, str, bool, None]
feature_importance: Sequence["InferenceFeatureImportance"]
top_classes: Sequence["InferenceTopClassEntry"]
warning: str
@@ -5307,7 +5271,7 @@ class InferenceTopClassEntry(AttrDict[Any]):
:arg class_score: (required)
"""
- class_name: Union[int, float, str, bool, None, Any]
+ class_name: Union[int, float, str, bool, None]
class_probability: float
class_score: float
@@ -5636,7 +5600,7 @@ class MultiTermsBucket(AttrDict[Any]):
:arg doc_count_error_upper_bound:
"""
- key: Sequence[Union[int, float, str, bool, None, Any]]
+ key: Sequence[Union[int, float, str, bool, None]]
doc_count: int
key_as_string: str
doc_count_error_upper_bound: int
@@ -6187,7 +6151,7 @@ class StringTermsBucket(AttrDict[Any]):
:arg doc_count_error_upper_bound:
"""
- key: Union[int, float, str, bool, None, Any]
+ key: Union[int, float, str, bool, None]
doc_count: int
doc_count_error_upper_bound: int
@@ -6291,7 +6255,7 @@ class TimeSeriesBucket(AttrDict[Any]):
:arg doc_count: (required)
"""
- key: Mapping[str, Union[int, float, str, bool, None, Any]]
+ key: Mapping[str, Union[int, float, str, bool, None]]
doc_count: int
@@ -6311,8 +6275,8 @@ class TopMetrics(AttrDict[Any]):
:arg metrics: (required)
"""
- sort: Sequence[Union[Union[int, float, str, bool, None, Any], None]]
- metrics: Mapping[str, Union[Union[int, float, str, bool, None, Any], None]]
+ sort: Sequence[Union[Union[int, float, str, bool, None], None]]
+ metrics: Mapping[str, Union[Union[int, float, str, bool, None], None]]
class TopMetricsAggregate(AttrDict[Any]):
diff --git a/elasticsearch/dsl/wrappers.py b/elasticsearch/dsl/wrappers.py
index ecd2e1363..52e7af257 100644
--- a/elasticsearch/dsl/wrappers.py
+++ b/elasticsearch/dsl/wrappers.py
@@ -18,6 +18,7 @@
import operator
from typing import (
TYPE_CHECKING,
+ Any,
Callable,
ClassVar,
Dict,
@@ -117,3 +118,27 @@ def lower(self) -> Union[Tuple[RangeValT, bool], Tuple[None, Literal[False]]]:
if "gte" in self._d_:
return self._d_["gte"], True
return None, False
+
+
+class AggregationRange(AttrDict[Any]):
+ """
+ :arg from: Start of the range (inclusive).
+ :arg key: Custom key to return the range with.
+ :arg to: End of the range (exclusive).
+ """
+
+ def __init__(
+ self,
+ *,
+ from_: Any = None,
+ key: Optional[str] = None,
+ to: Any = None,
+ **kwargs: Any,
+ ):
+ if from_ is not None:
+ kwargs["from_"] = from_
+ if key is not None:
+ kwargs["key"] = key
+ if to is not None:
+ kwargs["to"] = to
+ super().__init__(kwargs)
diff --git a/utils/dsl-generator.py b/utils/dsl-generator.py
index 3841967e7..2aa12c53d 100644
--- a/utils/dsl-generator.py
+++ b/utils/dsl-generator.py
@@ -17,14 +17,13 @@
import json
import re
+import subprocess
import textwrap
from urllib.error import HTTPError
from urllib.request import urlopen
from jinja2 import Environment, PackageLoader, select_autoescape
-from elasticsearch import VERSION
-
jinja_env = Environment(
loader=PackageLoader("utils"),
autoescape=select_autoescape(),
@@ -38,7 +37,7 @@
types_py = jinja_env.get_template("types.py.tpl")
# map with name replacements for Elasticsearch attributes
-PROP_REPLACEMENTS = {"from": "from_"}
+PROP_REPLACEMENTS = {"from": "from_", "global": "global_"}
# map with Elasticsearch type replacements
# keys and values are in given in "{namespace}:{name}" format
@@ -115,9 +114,9 @@ def type_for_types_py(type_):
class ElasticsearchSchema:
"""Operations related to the Elasticsearch schema."""
- def __init__(self):
+ def __init__(self, version="main"):
response = None
- for branch in [f"{VERSION[0]}.{VERSION[1]}", "main"]:
+ for branch in [version, "main"]:
url = f"https://raw.githubusercontent.com/elastic/elasticsearch-specification/{branch}/output/schema/schema.json"
try:
response = urlopen(url)
@@ -201,6 +200,12 @@ def get_python_type(self, schema_type, for_response=False):
):
# QueryContainer maps to the DSL's Query class
return "Query", {"type": "query"}
+ elif (
+ type_name["namespace"] == "_global.search._types"
+ and type_name["name"] == "SearchRequestBody"
+ ):
+ # we currently do not provide specific typing for this one
+ return "Dict[str, Any]", None
elif (
type_name["namespace"] == "_types.query_dsl"
and type_name["name"] == "FunctionScoreContainer"
@@ -219,7 +224,7 @@ def get_python_type(self, schema_type, for_response=False):
type_name["namespace"] == "_types.aggregations"
and type_name["name"] == "CompositeAggregationSource"
):
- # QueryContainer maps to the DSL's Query class
+ # CompositeAggreagationSource maps to the DSL's Agg class
return "Agg[_R]", None
else:
# for any other instances we get the type and recurse
@@ -300,6 +305,8 @@ def get_python_type(self, schema_type, for_response=False):
]
)
)
+ if len(types) == 1:
+ return types[0]
return "Union[" + ", ".join([type_ for type_, _ in types]) + "]", None
elif schema_type["kind"] == "enum":
@@ -338,6 +345,12 @@ def get_python_type(self, schema_type, for_response=False):
]["name"].endswith("Analyzer"):
# not expanding analyzers at this time, maybe in the future
return "str, Dict[str, Any]", None
+ elif (
+ schema_type["name"]["namespace"] == "_types.aggregations"
+ and schema_type["name"]["name"].endswith("AggregationRange")
+ and schema_type["name"]["name"] != "IpRangeAggregationRange"
+ ):
+ return '"wrappers.AggregationRange"', None
# to handle other interfaces we generate a type of the same name
# and add the interface to the interfaces.py module
@@ -380,9 +393,12 @@ def add_attribute(self, k, arg, for_types_py=False, for_response=False):
param = None
if not for_response:
if type_ != "Any":
- if 'Sequence["types.' in type_:
+ if (
+ 'Sequence["types.' in type_
+ or 'Sequence["wrappers.AggregationRange' in type_
+ ):
type_ = add_seq_dict_type(type_) # interfaces can be given as dicts
- elif "types." in type_:
+ elif "types." in type_ or "wrappers.AggregationRange" in type_:
type_ = add_dict_type(type_) # interfaces can be given as dicts
type_ = add_not_set(type_)
if for_types_py:
@@ -999,7 +1015,8 @@ def generate_types_py(schema, filename):
if __name__ == "__main__":
- schema = ElasticsearchSchema()
+ v = subprocess.check_output(["git", "branch", "--show-current"]).strip().decode()
+ schema = ElasticsearchSchema(v)
generate_field_py(schema, "elasticsearch/dsl/field.py")
generate_query_py(schema, "elasticsearch/dsl/query.py")
generate_aggs_py(schema, "elasticsearch/dsl/aggs.py")
diff --git a/utils/templates/aggs.py.tpl b/utils/templates/aggs.py.tpl
index d4ba4f4cd..68d46e63d 100644
--- a/utils/templates/aggs.py.tpl
+++ b/utils/templates/aggs.py.tpl
@@ -38,6 +38,7 @@ from elastic_transport.client_utils import DEFAULT
from .query import Query
from .response.aggs import AggResponse, BucketData, FieldBucketData, TopHitsData
from .utils import _R, AttrDict, DslBase
+from . import wrappers
if TYPE_CHECKING:
from elastic_transport.client_utils import DefaultType
From ea46777916d3db58910410f9e6a09fb40b7b54bd Mon Sep 17 00:00:00 2001
From: Elastic Machine
Date: Tue, 1 Apr 2025 12:32:02 +0100
Subject: [PATCH 11/57] Auto-generated API code (#2863)
Co-authored-by: Quentin Pradet
---
elasticsearch/_async/client/__init__.py | 16 +-
elasticsearch/_async/client/inference.py | 1513 +++++++++++++++++++++-
elasticsearch/_sync/client/__init__.py | 16 +-
elasticsearch/_sync/client/inference.py | 1513 +++++++++++++++++++++-
4 files changed, 3014 insertions(+), 44 deletions(-)
diff --git a/elasticsearch/_async/client/__init__.py b/elasticsearch/_async/client/__init__.py
index a897f2d37..4eab35bb0 100644
--- a/elasticsearch/_async/client/__init__.py
+++ b/elasticsearch/_async/client/__init__.py
@@ -1581,7 +1581,7 @@ async def delete_by_query(
If the request can target data streams, this argument determines whether
wildcard expressions match hidden data streams. It supports comma-separated
values, such as `open,hidden`.
- :param from_: Starting offset (default: 0)
+ :param from_: Skips the specified number of documents.
:param ignore_unavailable: If `false`, the request returns an error if it targets
a missing or closed index.
:param lenient: If `true`, format-based query failures (such as providing text
@@ -3420,7 +3420,8 @@ async def msearch(
computationally expensive named queries on a large number of hits may add
significant overhead.
:param max_concurrent_searches: Maximum number of concurrent searches the multi
- search API can execute.
+ search API can execute. Defaults to `max(1, (# of data nodes * min(search
+ thread pool size, 10)))`.
:param max_concurrent_shard_requests: Maximum number of concurrent shard requests
that each sub-search request executes per node.
:param pre_filter_shard_size: Defines a threshold that enforces a pre-filter
@@ -3748,6 +3749,7 @@ async def open_point_in_time(
human: t.Optional[bool] = None,
ignore_unavailable: t.Optional[bool] = None,
index_filter: t.Optional[t.Mapping[str, t.Any]] = None,
+ max_concurrent_shard_requests: t.Optional[int] = None,
preference: t.Optional[str] = None,
pretty: t.Optional[bool] = None,
routing: t.Optional[str] = None,
@@ -3803,6 +3805,8 @@ async def open_point_in_time(
a missing or closed index.
:param index_filter: Filter indices if the provided query rewrites to `match_none`
on every shard.
+ :param max_concurrent_shard_requests: Maximum number of concurrent shard requests
+ that each sub-search request executes per node.
:param preference: The node or shard the operation should be performed on. By
default, it is random.
:param routing: A custom value that is used to route operations to a specific
@@ -3830,6 +3834,8 @@ async def open_point_in_time(
__query["human"] = human
if ignore_unavailable is not None:
__query["ignore_unavailable"] = ignore_unavailable
+ if max_concurrent_shard_requests is not None:
+ __query["max_concurrent_shard_requests"] = max_concurrent_shard_requests
if preference is not None:
__query["preference"] = preference
if pretty is not None:
@@ -4370,7 +4376,7 @@ async def render_search_template(
human: t.Optional[bool] = None,
params: t.Optional[t.Mapping[str, t.Any]] = None,
pretty: t.Optional[bool] = None,
- source: t.Optional[str] = None,
+ source: t.Optional[t.Union[str, t.Mapping[str, t.Any]]] = None,
body: t.Optional[t.Dict[str, t.Any]] = None,
) -> ObjectApiResponse[t.Any]:
"""
@@ -5774,7 +5780,7 @@ async def search_template(
search_type: t.Optional[
t.Union[str, t.Literal["dfs_query_then_fetch", "query_then_fetch"]]
] = None,
- source: t.Optional[str] = None,
+ source: t.Optional[t.Union[str, t.Mapping[str, t.Any]]] = None,
typed_keys: t.Optional[bool] = None,
body: t.Optional[t.Dict[str, t.Any]] = None,
) -> ObjectApiResponse[t.Any]:
@@ -6512,7 +6518,7 @@ async def update_by_query(
wildcard expressions match hidden data streams. It supports comma-separated
values, such as `open,hidden`. Valid values are: `all`, `open`, `closed`,
`hidden`, `none`.
- :param from_: Starting offset (default: 0)
+ :param from_: Skips the specified number of documents.
:param ignore_unavailable: If `false`, the request returns an error if it targets
a missing or closed index.
:param lenient: If `true`, format-based query failures (such as providing text
diff --git a/elasticsearch/_async/client/inference.py b/elasticsearch/_async/client/inference.py
index ce96dba63..73983f07a 100644
--- a/elasticsearch/_async/client/inference.py
+++ b/elasticsearch/_async/client/inference.py
@@ -234,6 +234,67 @@ async def get(
path_parts=__path_parts,
)
+ @_rewrite_parameters(
+ body_name="chat_completion_request",
+ )
+ async def post_eis_chat_completion(
+ self,
+ *,
+ eis_inference_id: str,
+ chat_completion_request: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Perform a chat completion task through the Elastic Inference Service (EIS).
+
Perform a chat completion inference task with the elastic service.
+
+
+ ``_
+
+ :param eis_inference_id: The unique identifier of the inference endpoint.
+ :param chat_completion_request:
+ """
+ if eis_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'eis_inference_id'")
+ if chat_completion_request is None and body is None:
+ raise ValueError(
+ "Empty value passed for parameters 'chat_completion_request' and 'body', one of them should be set."
+ )
+ elif chat_completion_request is not None and body is not None:
+ raise ValueError("Cannot set both 'chat_completion_request' and 'body'")
+ __path_parts: t.Dict[str, str] = {"eis_inference_id": _quote(eis_inference_id)}
+ __path = (
+ f'/_inference/chat_completion/{__path_parts["eis_inference_id"]}/_stream'
+ )
+ __query: t.Dict[str, t.Any] = {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ __body = (
+ chat_completion_request if chat_completion_request is not None else body
+ )
+ __headers = {"accept": "application/json", "content-type": "application/json"}
+ return await self.perform_request( # type: ignore[return-value]
+ "POST",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.post_eis_chat_completion",
+ path_parts=__path_parts,
+ )
+
@_rewrite_parameters(
body_name="inference_config",
)
@@ -329,14 +390,14 @@ async def put(
"task_settings",
),
)
- async def put_openai(
+ async def put_alibabacloud(
self,
*,
task_type: t.Union[
- str, t.Literal["chat_completion", "completion", "text_embedding"]
+ str, t.Literal["completion", "rerank", "space_embedding", "text_embedding"]
],
- openai_inference_id: str,
- service: t.Optional[t.Union[str, t.Literal["openai"]]] = None,
+ alibabacloud_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["alibabacloud-ai-search"]]] = None,
service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
error_trace: t.Optional[bool] = None,
@@ -349,8 +410,8 @@ async def put_openai(
"""
.. raw:: html
-
Create an OpenAI inference endpoint.
-
Create an inference endpoint to perform an inference task with the openai service.
+
Create an AlibabaCloud AI Search inference endpoint.
+
Create an inference endpoint to perform an inference task with the alibabacloud-ai-search service.
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
After creating the endpoint, wait for the model deployment to complete before using it.
To verify the deployment status, use the get trained model statistics API.
@@ -358,33 +419,33 @@ async def put_openai(
Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
- ``_
+ ``_
:param task_type: The type of the inference task that the model will perform.
- NOTE: The `chat_completion` task type only supports streaming and only through
- the _stream API.
- :param openai_inference_id: The unique identifier of the inference endpoint.
+ :param alibabacloud_inference_id: The unique identifier of the inference endpoint.
:param service: The type of service supported for the specified task type. In
- this case, `openai`.
+ this case, `alibabacloud-ai-search`.
:param service_settings: Settings used to install the inference model. These
- settings are specific to the `openai` service.
+ settings are specific to the `alibabacloud-ai-search` service.
:param chunking_settings: The chunking configuration object.
:param task_settings: Settings to configure the inference task. These settings
are specific to the task type you specified.
"""
if task_type in SKIP_IN_PATH:
raise ValueError("Empty value passed for parameter 'task_type'")
- if openai_inference_id in SKIP_IN_PATH:
- raise ValueError("Empty value passed for parameter 'openai_inference_id'")
+ if alibabacloud_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'alibabacloud_inference_id'"
+ )
if service is None and body is None:
raise ValueError("Empty value passed for parameter 'service'")
if service_settings is None and body is None:
raise ValueError("Empty value passed for parameter 'service_settings'")
__path_parts: t.Dict[str, str] = {
"task_type": _quote(task_type),
- "openai_inference_id": _quote(openai_inference_id),
+ "alibabacloud_inference_id": _quote(alibabacloud_inference_id),
}
- __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["openai_inference_id"]}'
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["alibabacloud_inference_id"]}'
__query: t.Dict[str, t.Any] = {}
__body: t.Dict[str, t.Any] = body if body is not None else {}
if error_trace is not None:
@@ -415,7 +476,1425 @@ async def put_openai(
params=__query,
headers=__headers,
body=__body,
- endpoint_id="inference.put_openai",
+ endpoint_id="inference.put_alibabacloud",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ async def put_amazonbedrock(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["completion", "text_embedding"]],
+ amazonbedrock_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["amazonbedrock"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Amazon Bedrock inference endpoint.
+
Creates an inference endpoint to perform an inference task with the amazonbedrock service.
+
+
info
+ You need to provide the access and secret keys only once, during the inference model creation. The get inference API does not retrieve your access or secret keys. After creating the inference model, you cannot change the associated key pairs. If you want to use a different access and secret key pair, delete the inference model and recreate it with the same name and the updated keys.
+
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param amazonbedrock_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `amazonbedrock`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `amazonbedrock` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if amazonbedrock_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'amazonbedrock_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "amazonbedrock_inference_id": _quote(amazonbedrock_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["amazonbedrock_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_amazonbedrock",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ async def put_anthropic(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["completion"]],
+ anthropic_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["anthropic"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Anthropic inference endpoint.
+
Create an inference endpoint to perform an inference task with the anthropic service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The task type. The only valid task type for the model to perform
+ is `completion`.
+ :param anthropic_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `anthropic`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `watsonxai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if anthropic_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'anthropic_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "anthropic_inference_id": _quote(anthropic_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["anthropic_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_anthropic",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ async def put_azureaistudio(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["completion", "text_embedding"]],
+ azureaistudio_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["azureaistudio"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Azure AI studio inference endpoint.
+
Create an inference endpoint to perform an inference task with the azureaistudio service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param azureaistudio_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `azureaistudio`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `openai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if azureaistudio_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'azureaistudio_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "azureaistudio_inference_id": _quote(azureaistudio_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["azureaistudio_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_azureaistudio",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ async def put_azureopenai(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["completion", "text_embedding"]],
+ azureopenai_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["azureopenai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Azure OpenAI inference endpoint.
+
Create an inference endpoint to perform an inference task with the azureopenai service.
+
The list of chat completion models that you can choose from in your Azure OpenAI deployment include:
The list of embeddings models that you can choose from in your deployment can be found in the Azure models documentation.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ NOTE: The `chat_completion` task type only supports streaming and only through
+ the _stream API.
+ :param azureopenai_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `azureopenai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `azureopenai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if azureopenai_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'azureopenai_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "azureopenai_inference_id": _quote(azureopenai_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["azureopenai_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_azureopenai",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ async def put_cohere(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["completion", "rerank", "text_embedding"]],
+ cohere_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["cohere"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create a Cohere inference endpoint.
+
Create an inference endpoint to perform an inference task with the cohere service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param cohere_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `cohere`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `cohere` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if cohere_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'cohere_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "cohere_inference_id": _quote(cohere_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["cohere_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_cohere",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("service", "service_settings"),
+ )
+ async def put_eis(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["chat_completion"]],
+ eis_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["elastic"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Elastic Inference Service (EIS) inference endpoint.
+
Create an inference endpoint to perform an inference task through the Elastic Inference Service (EIS).
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ NOTE: The `chat_completion` task type only supports streaming and only through
+ the _stream API.
+ :param eis_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `elastic`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `elastic` service.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if eis_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'eis_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "eis_inference_id": _quote(eis_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["eis_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_eis",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ async def put_elasticsearch(
+ self,
+ *,
+ task_type: t.Union[
+ str, t.Literal["rerank", "sparse_embedding", "text_embedding"]
+ ],
+ elasticsearch_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["elasticsearch"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Elasticsearch inference endpoint.
+
Create an inference endpoint to perform an inference task with the elasticsearch service.
+
+
info
+ Your Elasticsearch deployment contains preconfigured ELSER and E5 inference endpoints, you only need to create the enpoints using the API if you want to customize the settings.
+
+
If you use the ELSER or the E5 model through the elasticsearch service, the API request will automatically download and deploy the model if it isn't downloaded yet.
+
+
info
+ You might see a 502 bad gateway error in the response when using the Kibana Console. This error usually just reflects a timeout, while the model downloads in the background. You can check the download progress in the Machine Learning UI. If using the Python client, you can set the timeout parameter to a higher value.
+
+
After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param elasticsearch_inference_id: The unique identifier of the inference endpoint.
+ The must not match the `model_id`.
+ :param service: The type of service supported for the specified task type. In
+ this case, `elasticsearch`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `elasticsearch` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if elasticsearch_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'elasticsearch_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "elasticsearch_inference_id": _quote(elasticsearch_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["elasticsearch_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_elasticsearch",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("service", "service_settings", "chunking_settings"),
+ )
+ async def put_elser(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["sparse_embedding"]],
+ elser_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["elser"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an ELSER inference endpoint.
+
Create an inference endpoint to perform an inference task with the elser service.
+ You can also deploy ELSER by using the Elasticsearch inference integration.
+
+
info
+ Your Elasticsearch deployment contains a preconfigured ELSER inference endpoint, you only need to create the enpoint using the API if you want to customize the settings.
+
+
The API request will automatically download and deploy the ELSER model if it isn't already downloaded.
+
+
info
+ You might see a 502 bad gateway error in the response when using the Kibana Console. This error usually just reflects a timeout, while the model downloads in the background. You can check the download progress in the Machine Learning UI. If using the Python client, you can set the timeout parameter to a higher value.
+
+
After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param elser_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `elser`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `elser` service.
+ :param chunking_settings: The chunking configuration object.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if elser_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'elser_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "elser_inference_id": _quote(elser_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["elser_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_elser",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("service", "service_settings", "chunking_settings"),
+ )
+ async def put_googleaistudio(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["completion", "text_embedding"]],
+ googleaistudio_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["googleaistudio"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Google AI Studio inference endpoint.
+
Create an inference endpoint to perform an inference task with the googleaistudio service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param googleaistudio_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `googleaistudio`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `googleaistudio` service.
+ :param chunking_settings: The chunking configuration object.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if googleaistudio_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'googleaistudio_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "googleaistudio_inference_id": _quote(googleaistudio_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["googleaistudio_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_googleaistudio",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ async def put_googlevertexai(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["rerank", "text_embedding"]],
+ googlevertexai_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["googlevertexai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create a Google Vertex AI inference endpoint.
+
Create an inference endpoint to perform an inference task with the googlevertexai service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param googlevertexai_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `googlevertexai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `googlevertexai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if googlevertexai_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'googlevertexai_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "googlevertexai_inference_id": _quote(googlevertexai_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["googlevertexai_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_googlevertexai",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("service", "service_settings", "chunking_settings"),
+ )
+ async def put_hugging_face(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["text_embedding"]],
+ huggingface_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["hugging_face"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create a Hugging Face inference endpoint.
+
Create an inference endpoint to perform an inference task with the hugging_face service.
+
You must first create an inference endpoint on the Hugging Face endpoint page to get an endpoint URL.
+ Select the model you want to use on the new endpoint creation page (for example intfloat/e5-small-v2), then select the sentence embeddings task under the advanced configuration section.
+ Create the endpoint and copy the URL after the endpoint initialization has been finished.
+
The following models are recommended for the Hugging Face service:
+
+
all-MiniLM-L6-v2
+
all-MiniLM-L12-v2
+
all-mpnet-base-v2
+
e5-base-v2
+
e5-small-v2
+
multilingual-e5-base
+
multilingual-e5-small
+
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param huggingface_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `hugging_face`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `hugging_face` service.
+ :param chunking_settings: The chunking configuration object.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if huggingface_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'huggingface_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "huggingface_inference_id": _quote(huggingface_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["huggingface_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_hugging_face",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ async def put_jinaai(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["rerank", "text_embedding"]],
+ jinaai_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["jinaai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an JinaAI inference endpoint.
+
Create an inference endpoint to perform an inference task with the jinaai service.
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param jinaai_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `jinaai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `jinaai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if jinaai_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'jinaai_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "jinaai_inference_id": _quote(jinaai_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["jinaai_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_jinaai",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("service", "service_settings", "chunking_settings"),
+ )
+ async def put_mistral(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["text_embedding"]],
+ mistral_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["mistral"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create a Mistral inference endpoint.
+
Creates an inference endpoint to perform an inference task with the mistral service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The task type. The only valid task type for the model to perform
+ is `text_embedding`.
+ :param mistral_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `mistral`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `mistral` service.
+ :param chunking_settings: The chunking configuration object.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if mistral_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'mistral_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "mistral_inference_id": _quote(mistral_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["mistral_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_mistral",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ async def put_openai(
+ self,
+ *,
+ task_type: t.Union[
+ str, t.Literal["chat_completion", "completion", "text_embedding"]
+ ],
+ openai_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["openai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an OpenAI inference endpoint.
+
Create an inference endpoint to perform an inference task with the openai service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ NOTE: The `chat_completion` task type only supports streaming and only through
+ the _stream API.
+ :param openai_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `openai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `openai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if openai_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'openai_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "openai_inference_id": _quote(openai_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["openai_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_openai",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ async def put_voyageai(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["rerank", "text_embedding"]],
+ voyageai_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["voyageai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create a VoyageAI inference endpoint.
+
Create an inference endpoint to perform an inference task with the voyageai service.
+
Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param voyageai_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `voyageai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `voyageai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if voyageai_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'voyageai_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "voyageai_inference_id": _quote(voyageai_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["voyageai_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_voyageai",
path_parts=__path_parts,
)
diff --git a/elasticsearch/_sync/client/__init__.py b/elasticsearch/_sync/client/__init__.py
index 1d80efee7..d4082ceb1 100644
--- a/elasticsearch/_sync/client/__init__.py
+++ b/elasticsearch/_sync/client/__init__.py
@@ -1579,7 +1579,7 @@ def delete_by_query(
If the request can target data streams, this argument determines whether
wildcard expressions match hidden data streams. It supports comma-separated
values, such as `open,hidden`.
- :param from_: Starting offset (default: 0)
+ :param from_: Skips the specified number of documents.
:param ignore_unavailable: If `false`, the request returns an error if it targets
a missing or closed index.
:param lenient: If `true`, format-based query failures (such as providing text
@@ -3418,7 +3418,8 @@ def msearch(
computationally expensive named queries on a large number of hits may add
significant overhead.
:param max_concurrent_searches: Maximum number of concurrent searches the multi
- search API can execute.
+ search API can execute. Defaults to `max(1, (# of data nodes * min(search
+ thread pool size, 10)))`.
:param max_concurrent_shard_requests: Maximum number of concurrent shard requests
that each sub-search request executes per node.
:param pre_filter_shard_size: Defines a threshold that enforces a pre-filter
@@ -3746,6 +3747,7 @@ def open_point_in_time(
human: t.Optional[bool] = None,
ignore_unavailable: t.Optional[bool] = None,
index_filter: t.Optional[t.Mapping[str, t.Any]] = None,
+ max_concurrent_shard_requests: t.Optional[int] = None,
preference: t.Optional[str] = None,
pretty: t.Optional[bool] = None,
routing: t.Optional[str] = None,
@@ -3801,6 +3803,8 @@ def open_point_in_time(
a missing or closed index.
:param index_filter: Filter indices if the provided query rewrites to `match_none`
on every shard.
+ :param max_concurrent_shard_requests: Maximum number of concurrent shard requests
+ that each sub-search request executes per node.
:param preference: The node or shard the operation should be performed on. By
default, it is random.
:param routing: A custom value that is used to route operations to a specific
@@ -3828,6 +3832,8 @@ def open_point_in_time(
__query["human"] = human
if ignore_unavailable is not None:
__query["ignore_unavailable"] = ignore_unavailable
+ if max_concurrent_shard_requests is not None:
+ __query["max_concurrent_shard_requests"] = max_concurrent_shard_requests
if preference is not None:
__query["preference"] = preference
if pretty is not None:
@@ -4368,7 +4374,7 @@ def render_search_template(
human: t.Optional[bool] = None,
params: t.Optional[t.Mapping[str, t.Any]] = None,
pretty: t.Optional[bool] = None,
- source: t.Optional[str] = None,
+ source: t.Optional[t.Union[str, t.Mapping[str, t.Any]]] = None,
body: t.Optional[t.Dict[str, t.Any]] = None,
) -> ObjectApiResponse[t.Any]:
"""
@@ -5772,7 +5778,7 @@ def search_template(
search_type: t.Optional[
t.Union[str, t.Literal["dfs_query_then_fetch", "query_then_fetch"]]
] = None,
- source: t.Optional[str] = None,
+ source: t.Optional[t.Union[str, t.Mapping[str, t.Any]]] = None,
typed_keys: t.Optional[bool] = None,
body: t.Optional[t.Dict[str, t.Any]] = None,
) -> ObjectApiResponse[t.Any]:
@@ -6510,7 +6516,7 @@ def update_by_query(
wildcard expressions match hidden data streams. It supports comma-separated
values, such as `open,hidden`. Valid values are: `all`, `open`, `closed`,
`hidden`, `none`.
- :param from_: Starting offset (default: 0)
+ :param from_: Skips the specified number of documents.
:param ignore_unavailable: If `false`, the request returns an error if it targets
a missing or closed index.
:param lenient: If `true`, format-based query failures (such as providing text
diff --git a/elasticsearch/_sync/client/inference.py b/elasticsearch/_sync/client/inference.py
index 6bab33aec..279528a96 100644
--- a/elasticsearch/_sync/client/inference.py
+++ b/elasticsearch/_sync/client/inference.py
@@ -234,6 +234,67 @@ def get(
path_parts=__path_parts,
)
+ @_rewrite_parameters(
+ body_name="chat_completion_request",
+ )
+ def post_eis_chat_completion(
+ self,
+ *,
+ eis_inference_id: str,
+ chat_completion_request: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Perform a chat completion task through the Elastic Inference Service (EIS).
+
Perform a chat completion inference task with the elastic service.
+
+
+ ``_
+
+ :param eis_inference_id: The unique identifier of the inference endpoint.
+ :param chat_completion_request:
+ """
+ if eis_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'eis_inference_id'")
+ if chat_completion_request is None and body is None:
+ raise ValueError(
+ "Empty value passed for parameters 'chat_completion_request' and 'body', one of them should be set."
+ )
+ elif chat_completion_request is not None and body is not None:
+ raise ValueError("Cannot set both 'chat_completion_request' and 'body'")
+ __path_parts: t.Dict[str, str] = {"eis_inference_id": _quote(eis_inference_id)}
+ __path = (
+ f'/_inference/chat_completion/{__path_parts["eis_inference_id"]}/_stream'
+ )
+ __query: t.Dict[str, t.Any] = {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ __body = (
+ chat_completion_request if chat_completion_request is not None else body
+ )
+ __headers = {"accept": "application/json", "content-type": "application/json"}
+ return self.perform_request( # type: ignore[return-value]
+ "POST",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.post_eis_chat_completion",
+ path_parts=__path_parts,
+ )
+
@_rewrite_parameters(
body_name="inference_config",
)
@@ -329,14 +390,14 @@ def put(
"task_settings",
),
)
- def put_openai(
+ def put_alibabacloud(
self,
*,
task_type: t.Union[
- str, t.Literal["chat_completion", "completion", "text_embedding"]
+ str, t.Literal["completion", "rerank", "space_embedding", "text_embedding"]
],
- openai_inference_id: str,
- service: t.Optional[t.Union[str, t.Literal["openai"]]] = None,
+ alibabacloud_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["alibabacloud-ai-search"]]] = None,
service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
error_trace: t.Optional[bool] = None,
@@ -349,8 +410,8 @@ def put_openai(
"""
.. raw:: html
-
Create an OpenAI inference endpoint.
-
Create an inference endpoint to perform an inference task with the openai service.
+
Create an AlibabaCloud AI Search inference endpoint.
+
Create an inference endpoint to perform an inference task with the alibabacloud-ai-search service.
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
After creating the endpoint, wait for the model deployment to complete before using it.
To verify the deployment status, use the get trained model statistics API.
@@ -358,33 +419,33 @@ def put_openai(
Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
- ``_
+ ``_
:param task_type: The type of the inference task that the model will perform.
- NOTE: The `chat_completion` task type only supports streaming and only through
- the _stream API.
- :param openai_inference_id: The unique identifier of the inference endpoint.
+ :param alibabacloud_inference_id: The unique identifier of the inference endpoint.
:param service: The type of service supported for the specified task type. In
- this case, `openai`.
+ this case, `alibabacloud-ai-search`.
:param service_settings: Settings used to install the inference model. These
- settings are specific to the `openai` service.
+ settings are specific to the `alibabacloud-ai-search` service.
:param chunking_settings: The chunking configuration object.
:param task_settings: Settings to configure the inference task. These settings
are specific to the task type you specified.
"""
if task_type in SKIP_IN_PATH:
raise ValueError("Empty value passed for parameter 'task_type'")
- if openai_inference_id in SKIP_IN_PATH:
- raise ValueError("Empty value passed for parameter 'openai_inference_id'")
+ if alibabacloud_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'alibabacloud_inference_id'"
+ )
if service is None and body is None:
raise ValueError("Empty value passed for parameter 'service'")
if service_settings is None and body is None:
raise ValueError("Empty value passed for parameter 'service_settings'")
__path_parts: t.Dict[str, str] = {
"task_type": _quote(task_type),
- "openai_inference_id": _quote(openai_inference_id),
+ "alibabacloud_inference_id": _quote(alibabacloud_inference_id),
}
- __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["openai_inference_id"]}'
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["alibabacloud_inference_id"]}'
__query: t.Dict[str, t.Any] = {}
__body: t.Dict[str, t.Any] = body if body is not None else {}
if error_trace is not None:
@@ -415,7 +476,1425 @@ def put_openai(
params=__query,
headers=__headers,
body=__body,
- endpoint_id="inference.put_openai",
+ endpoint_id="inference.put_alibabacloud",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ def put_amazonbedrock(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["completion", "text_embedding"]],
+ amazonbedrock_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["amazonbedrock"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Amazon Bedrock inference endpoint.
+
Creates an inference endpoint to perform an inference task with the amazonbedrock service.
+
+
info
+ You need to provide the access and secret keys only once, during the inference model creation. The get inference API does not retrieve your access or secret keys. After creating the inference model, you cannot change the associated key pairs. If you want to use a different access and secret key pair, delete the inference model and recreate it with the same name and the updated keys.
+
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param amazonbedrock_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `amazonbedrock`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `amazonbedrock` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if amazonbedrock_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'amazonbedrock_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "amazonbedrock_inference_id": _quote(amazonbedrock_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["amazonbedrock_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_amazonbedrock",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ def put_anthropic(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["completion"]],
+ anthropic_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["anthropic"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Anthropic inference endpoint.
+
Create an inference endpoint to perform an inference task with the anthropic service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The task type. The only valid task type for the model to perform
+ is `completion`.
+ :param anthropic_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `anthropic`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `watsonxai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if anthropic_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'anthropic_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "anthropic_inference_id": _quote(anthropic_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["anthropic_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_anthropic",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ def put_azureaistudio(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["completion", "text_embedding"]],
+ azureaistudio_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["azureaistudio"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Azure AI studio inference endpoint.
+
Create an inference endpoint to perform an inference task with the azureaistudio service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param azureaistudio_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `azureaistudio`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `openai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if azureaistudio_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'azureaistudio_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "azureaistudio_inference_id": _quote(azureaistudio_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["azureaistudio_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_azureaistudio",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ def put_azureopenai(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["completion", "text_embedding"]],
+ azureopenai_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["azureopenai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Azure OpenAI inference endpoint.
+
Create an inference endpoint to perform an inference task with the azureopenai service.
+
The list of chat completion models that you can choose from in your Azure OpenAI deployment include:
The list of embeddings models that you can choose from in your deployment can be found in the Azure models documentation.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ NOTE: The `chat_completion` task type only supports streaming and only through
+ the _stream API.
+ :param azureopenai_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `azureopenai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `azureopenai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if azureopenai_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'azureopenai_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "azureopenai_inference_id": _quote(azureopenai_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["azureopenai_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_azureopenai",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ def put_cohere(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["completion", "rerank", "text_embedding"]],
+ cohere_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["cohere"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create a Cohere inference endpoint.
+
Create an inference endpoint to perform an inference task with the cohere service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param cohere_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `cohere`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `cohere` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if cohere_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'cohere_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "cohere_inference_id": _quote(cohere_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["cohere_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_cohere",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("service", "service_settings"),
+ )
+ def put_eis(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["chat_completion"]],
+ eis_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["elastic"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Elastic Inference Service (EIS) inference endpoint.
+
Create an inference endpoint to perform an inference task through the Elastic Inference Service (EIS).
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ NOTE: The `chat_completion` task type only supports streaming and only through
+ the _stream API.
+ :param eis_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `elastic`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `elastic` service.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if eis_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'eis_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "eis_inference_id": _quote(eis_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["eis_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_eis",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ def put_elasticsearch(
+ self,
+ *,
+ task_type: t.Union[
+ str, t.Literal["rerank", "sparse_embedding", "text_embedding"]
+ ],
+ elasticsearch_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["elasticsearch"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Elasticsearch inference endpoint.
+
Create an inference endpoint to perform an inference task with the elasticsearch service.
+
+
info
+ Your Elasticsearch deployment contains preconfigured ELSER and E5 inference endpoints, you only need to create the enpoints using the API if you want to customize the settings.
+
+
If you use the ELSER or the E5 model through the elasticsearch service, the API request will automatically download and deploy the model if it isn't downloaded yet.
+
+
info
+ You might see a 502 bad gateway error in the response when using the Kibana Console. This error usually just reflects a timeout, while the model downloads in the background. You can check the download progress in the Machine Learning UI. If using the Python client, you can set the timeout parameter to a higher value.
+
+
After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param elasticsearch_inference_id: The unique identifier of the inference endpoint.
+ The must not match the `model_id`.
+ :param service: The type of service supported for the specified task type. In
+ this case, `elasticsearch`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `elasticsearch` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if elasticsearch_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'elasticsearch_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "elasticsearch_inference_id": _quote(elasticsearch_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["elasticsearch_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_elasticsearch",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("service", "service_settings", "chunking_settings"),
+ )
+ def put_elser(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["sparse_embedding"]],
+ elser_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["elser"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an ELSER inference endpoint.
+
Create an inference endpoint to perform an inference task with the elser service.
+ You can also deploy ELSER by using the Elasticsearch inference integration.
+
+
info
+ Your Elasticsearch deployment contains a preconfigured ELSER inference endpoint, you only need to create the enpoint using the API if you want to customize the settings.
+
+
The API request will automatically download and deploy the ELSER model if it isn't already downloaded.
+
+
info
+ You might see a 502 bad gateway error in the response when using the Kibana Console. This error usually just reflects a timeout, while the model downloads in the background. You can check the download progress in the Machine Learning UI. If using the Python client, you can set the timeout parameter to a higher value.
+
+
After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param elser_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `elser`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `elser` service.
+ :param chunking_settings: The chunking configuration object.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if elser_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'elser_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "elser_inference_id": _quote(elser_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["elser_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_elser",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("service", "service_settings", "chunking_settings"),
+ )
+ def put_googleaistudio(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["completion", "text_embedding"]],
+ googleaistudio_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["googleaistudio"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an Google AI Studio inference endpoint.
+
Create an inference endpoint to perform an inference task with the googleaistudio service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param googleaistudio_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `googleaistudio`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `googleaistudio` service.
+ :param chunking_settings: The chunking configuration object.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if googleaistudio_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'googleaistudio_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "googleaistudio_inference_id": _quote(googleaistudio_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["googleaistudio_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_googleaistudio",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ def put_googlevertexai(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["rerank", "text_embedding"]],
+ googlevertexai_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["googlevertexai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create a Google Vertex AI inference endpoint.
+
Create an inference endpoint to perform an inference task with the googlevertexai service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param googlevertexai_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `googlevertexai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `googlevertexai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if googlevertexai_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'googlevertexai_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "googlevertexai_inference_id": _quote(googlevertexai_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["googlevertexai_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_googlevertexai",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("service", "service_settings", "chunking_settings"),
+ )
+ def put_hugging_face(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["text_embedding"]],
+ huggingface_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["hugging_face"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create a Hugging Face inference endpoint.
+
Create an inference endpoint to perform an inference task with the hugging_face service.
+
You must first create an inference endpoint on the Hugging Face endpoint page to get an endpoint URL.
+ Select the model you want to use on the new endpoint creation page (for example intfloat/e5-small-v2), then select the sentence embeddings task under the advanced configuration section.
+ Create the endpoint and copy the URL after the endpoint initialization has been finished.
+
The following models are recommended for the Hugging Face service:
+
+
all-MiniLM-L6-v2
+
all-MiniLM-L12-v2
+
all-mpnet-base-v2
+
e5-base-v2
+
e5-small-v2
+
multilingual-e5-base
+
multilingual-e5-small
+
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param huggingface_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `hugging_face`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `hugging_face` service.
+ :param chunking_settings: The chunking configuration object.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if huggingface_inference_id in SKIP_IN_PATH:
+ raise ValueError(
+ "Empty value passed for parameter 'huggingface_inference_id'"
+ )
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "huggingface_inference_id": _quote(huggingface_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["huggingface_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_hugging_face",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ def put_jinaai(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["rerank", "text_embedding"]],
+ jinaai_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["jinaai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an JinaAI inference endpoint.
+
Create an inference endpoint to perform an inference task with the jinaai service.
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param jinaai_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `jinaai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `jinaai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if jinaai_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'jinaai_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "jinaai_inference_id": _quote(jinaai_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["jinaai_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_jinaai",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=("service", "service_settings", "chunking_settings"),
+ )
+ def put_mistral(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["text_embedding"]],
+ mistral_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["mistral"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create a Mistral inference endpoint.
+
Creates an inference endpoint to perform an inference task with the mistral service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The task type. The only valid task type for the model to perform
+ is `text_embedding`.
+ :param mistral_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `mistral`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `mistral` service.
+ :param chunking_settings: The chunking configuration object.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if mistral_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'mistral_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "mistral_inference_id": _quote(mistral_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["mistral_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_mistral",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ def put_openai(
+ self,
+ *,
+ task_type: t.Union[
+ str, t.Literal["chat_completion", "completion", "text_embedding"]
+ ],
+ openai_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["openai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create an OpenAI inference endpoint.
+
Create an inference endpoint to perform an inference task with the openai service.
+
When you create an inference endpoint, the associated machine learning model is automatically deployed if it is not already running.
+ After creating the endpoint, wait for the model deployment to complete before using it.
+ To verify the deployment status, use the get trained model statistics API.
+ Look for "state": "fully_allocated" in the response and ensure that the "allocation_count" matches the "target_allocation_count".
+ Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ NOTE: The `chat_completion` task type only supports streaming and only through
+ the _stream API.
+ :param openai_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `openai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `openai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if openai_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'openai_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "openai_inference_id": _quote(openai_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["openai_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_openai",
+ path_parts=__path_parts,
+ )
+
+ @_rewrite_parameters(
+ body_fields=(
+ "service",
+ "service_settings",
+ "chunking_settings",
+ "task_settings",
+ ),
+ )
+ def put_voyageai(
+ self,
+ *,
+ task_type: t.Union[str, t.Literal["rerank", "text_embedding"]],
+ voyageai_inference_id: str,
+ service: t.Optional[t.Union[str, t.Literal["voyageai"]]] = None,
+ service_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ chunking_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ task_settings: t.Optional[t.Mapping[str, t.Any]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Create a VoyageAI inference endpoint.
+
Create an inference endpoint to perform an inference task with the voyageai service.
+
Avoid creating multiple endpoints for the same model unless required, as each endpoint consumes significant resources.
+
+
+ ``_
+
+ :param task_type: The type of the inference task that the model will perform.
+ :param voyageai_inference_id: The unique identifier of the inference endpoint.
+ :param service: The type of service supported for the specified task type. In
+ this case, `voyageai`.
+ :param service_settings: Settings used to install the inference model. These
+ settings are specific to the `voyageai` service.
+ :param chunking_settings: The chunking configuration object.
+ :param task_settings: Settings to configure the inference task. These settings
+ are specific to the task type you specified.
+ """
+ if task_type in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'task_type'")
+ if voyageai_inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'voyageai_inference_id'")
+ if service is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service'")
+ if service_settings is None and body is None:
+ raise ValueError("Empty value passed for parameter 'service_settings'")
+ __path_parts: t.Dict[str, str] = {
+ "task_type": _quote(task_type),
+ "voyageai_inference_id": _quote(voyageai_inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["voyageai_inference_id"]}'
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if not __body:
+ if service is not None:
+ __body["service"] = service
+ if service_settings is not None:
+ __body["service_settings"] = service_settings
+ if chunking_settings is not None:
+ __body["chunking_settings"] = chunking_settings
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "PUT",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.put_voyageai",
path_parts=__path_parts,
)
From 59deef20c7e7f1d2d19dd94dc5b5d94ce5be58a4 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 2 Apr 2025 14:43:01 +0100
Subject: [PATCH 12/57] Remove deprecated http_auth parameter (#2839) (#2875)
(cherry picked from commit 74387d0a3f42517e2a5805c9bb0aec57511b6e15)
Co-authored-by: Quentin Pradet
---
elasticsearch/_async/client/__init__.py | 21 -----
elasticsearch/_async/client/_base.py | 26 ------
elasticsearch/_async/client/utils.py | 4 -
elasticsearch/_async/helpers.py | 7 +-
elasticsearch/_sync/client/__init__.py | 21 -----
elasticsearch/_sync/client/_base.py | 26 ------
elasticsearch/_sync/client/utils.py | 35 --------
elasticsearch/helpers/actions.py | 6 +-
.../test_async/test_server/test_helpers.py | 6 +-
.../test_client/test_deprecated_options.py | 26 ------
.../test_client/test_requests_auth.py | 84 -------------------
.../test_client/test_rewrite_parameters.py | 4 +-
.../test_server/test_helpers.py | 7 +-
13 files changed, 8 insertions(+), 265 deletions(-)
delete mode 100644 test_elasticsearch/test_client/test_requests_auth.py
diff --git a/elasticsearch/_async/client/__init__.py b/elasticsearch/_async/client/__init__.py
index 4eab35bb0..14ada0e22 100644
--- a/elasticsearch/_async/client/__init__.py
+++ b/elasticsearch/_async/client/__init__.py
@@ -88,8 +88,6 @@
_rewrite_parameters,
_stability_warning,
client_node_configs,
- is_requests_http_auth,
- is_requests_node_class,
)
from .watcher import WatcherClient
from .xpack import XPackClient
@@ -191,7 +189,6 @@ def __init__(
] = None,
sniffer_timeout: t.Union[DefaultType, None, float] = DEFAULT,
sniff_on_connection_fail: t.Union[DefaultType, bool] = DEFAULT,
- http_auth: t.Union[DefaultType, t.Any] = DEFAULT,
maxsize: t.Union[DefaultType, int] = DEFAULT,
# Internal use only
_transport: t.Optional[AsyncTransport] = None,
@@ -320,26 +317,9 @@ def __init__(
sniff_callback = default_sniff_callback
if _transport is None:
- requests_session_auth = None
- if http_auth is not None and http_auth is not DEFAULT:
- if is_requests_http_auth(http_auth):
- # If we're using custom requests authentication
- # then we need to alert the user that they also
- # need to use 'node_class=requests'.
- if not is_requests_node_class(node_class):
- raise ValueError(
- "Using a custom 'requests.auth.AuthBase' class for "
- "'http_auth' must be used with node_class='requests'"
- )
-
- # Reset 'http_auth' to DEFAULT so it's not consumed below.
- requests_session_auth = http_auth
- http_auth = DEFAULT
-
node_configs = client_node_configs(
hosts,
cloud_id=cloud_id,
- requests_session_auth=requests_session_auth,
connections_per_node=connections_per_node,
http_compress=http_compress,
verify_certs=verify_certs,
@@ -426,7 +406,6 @@ def __init__(
self._headers["x-opaque-id"] = opaque_id
self._headers = resolve_auth_headers(
self._headers,
- http_auth=http_auth,
api_key=api_key,
basic_auth=basic_auth,
bearer_auth=bearer_auth,
diff --git a/elasticsearch/_async/client/_base.py b/elasticsearch/_async/client/_base.py
index cc090671c..3907cfd84 100644
--- a/elasticsearch/_async/client/_base.py
+++ b/elasticsearch/_async/client/_base.py
@@ -68,7 +68,6 @@
def resolve_auth_headers(
headers: Optional[Mapping[str, str]],
- http_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
api_key: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
basic_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
bearer_auth: Union[DefaultType, None, str] = DEFAULT,
@@ -78,32 +77,7 @@ def resolve_auth_headers(
elif not isinstance(headers, HttpHeaders):
headers = HttpHeaders(headers)
- resolved_http_auth = http_auth if http_auth is not DEFAULT else None
resolved_basic_auth = basic_auth if basic_auth is not DEFAULT else None
- if resolved_http_auth is not None:
- if resolved_basic_auth is not None:
- raise ValueError(
- "Can't specify both 'http_auth' and 'basic_auth', "
- "instead only specify 'basic_auth'"
- )
- if isinstance(http_auth, str) or (
- isinstance(resolved_http_auth, (list, tuple))
- and all(isinstance(x, str) for x in resolved_http_auth)
- ):
- resolved_basic_auth = resolved_http_auth
- else:
- raise TypeError(
- "The deprecated 'http_auth' parameter must be either 'Tuple[str, str]' or 'str'. "
- "Use either the 'basic_auth' parameter instead"
- )
-
- warnings.warn(
- "The 'http_auth' parameter is deprecated. "
- "Use 'basic_auth' or 'bearer_auth' parameters instead",
- category=DeprecationWarning,
- stacklevel=warn_stacklevel(),
- )
-
resolved_api_key = api_key if api_key is not DEFAULT else None
resolved_bearer_auth = bearer_auth if bearer_auth is not DEFAULT else None
if resolved_api_key or resolved_basic_auth or resolved_bearer_auth:
diff --git a/elasticsearch/_async/client/utils.py b/elasticsearch/_async/client/utils.py
index 97918d9e4..ac7a35062 100644
--- a/elasticsearch/_async/client/utils.py
+++ b/elasticsearch/_async/client/utils.py
@@ -27,8 +27,6 @@
_rewrite_parameters,
_stability_warning,
client_node_configs,
- is_requests_http_auth,
- is_requests_node_class,
)
__all__ = [
@@ -43,6 +41,4 @@
"client_node_configs",
"_rewrite_parameters",
"_stability_warning",
- "is_requests_http_auth",
- "is_requests_node_class",
]
diff --git a/elasticsearch/_async/helpers.py b/elasticsearch/_async/helpers.py
index e4d5e6bc5..8b5d3d0d2 100644
--- a/elasticsearch/_async/helpers.py
+++ b/elasticsearch/_async/helpers.py
@@ -418,12 +418,9 @@ def pop_transport_kwargs(kw: MutableMapping[str, Any]) -> MutableMapping[str, An
# Grab options that should be propagated to every
# API call within this helper instead of just 'search()'
transport_kwargs = {}
- for key in ("headers", "api_key", "http_auth", "basic_auth", "bearer_auth"):
+ for key in ("headers", "api_key", "basic_auth", "bearer_auth"):
try:
- value = kw.pop(key)
- if key == "http_auth":
- key = "basic_auth"
- transport_kwargs[key] = value
+ transport_kwargs[key] = kw.pop(key)
except KeyError:
pass
return transport_kwargs
diff --git a/elasticsearch/_sync/client/__init__.py b/elasticsearch/_sync/client/__init__.py
index d4082ceb1..46484630a 100644
--- a/elasticsearch/_sync/client/__init__.py
+++ b/elasticsearch/_sync/client/__init__.py
@@ -88,8 +88,6 @@
_rewrite_parameters,
_stability_warning,
client_node_configs,
- is_requests_http_auth,
- is_requests_node_class,
)
from .watcher import WatcherClient
from .xpack import XPackClient
@@ -191,7 +189,6 @@ def __init__(
] = None,
sniffer_timeout: t.Union[DefaultType, None, float] = DEFAULT,
sniff_on_connection_fail: t.Union[DefaultType, bool] = DEFAULT,
- http_auth: t.Union[DefaultType, t.Any] = DEFAULT,
maxsize: t.Union[DefaultType, int] = DEFAULT,
# Internal use only
_transport: t.Optional[Transport] = None,
@@ -320,26 +317,9 @@ def __init__(
sniff_callback = default_sniff_callback
if _transport is None:
- requests_session_auth = None
- if http_auth is not None and http_auth is not DEFAULT:
- if is_requests_http_auth(http_auth):
- # If we're using custom requests authentication
- # then we need to alert the user that they also
- # need to use 'node_class=requests'.
- if not is_requests_node_class(node_class):
- raise ValueError(
- "Using a custom 'requests.auth.AuthBase' class for "
- "'http_auth' must be used with node_class='requests'"
- )
-
- # Reset 'http_auth' to DEFAULT so it's not consumed below.
- requests_session_auth = http_auth
- http_auth = DEFAULT
-
node_configs = client_node_configs(
hosts,
cloud_id=cloud_id,
- requests_session_auth=requests_session_auth,
connections_per_node=connections_per_node,
http_compress=http_compress,
verify_certs=verify_certs,
@@ -426,7 +406,6 @@ def __init__(
self._headers["x-opaque-id"] = opaque_id
self._headers = resolve_auth_headers(
self._headers,
- http_auth=http_auth,
api_key=api_key,
basic_auth=basic_auth,
bearer_auth=bearer_auth,
diff --git a/elasticsearch/_sync/client/_base.py b/elasticsearch/_sync/client/_base.py
index 868b71073..64abdc250 100644
--- a/elasticsearch/_sync/client/_base.py
+++ b/elasticsearch/_sync/client/_base.py
@@ -68,7 +68,6 @@
def resolve_auth_headers(
headers: Optional[Mapping[str, str]],
- http_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
api_key: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
basic_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
bearer_auth: Union[DefaultType, None, str] = DEFAULT,
@@ -78,32 +77,7 @@ def resolve_auth_headers(
elif not isinstance(headers, HttpHeaders):
headers = HttpHeaders(headers)
- resolved_http_auth = http_auth if http_auth is not DEFAULT else None
resolved_basic_auth = basic_auth if basic_auth is not DEFAULT else None
- if resolved_http_auth is not None:
- if resolved_basic_auth is not None:
- raise ValueError(
- "Can't specify both 'http_auth' and 'basic_auth', "
- "instead only specify 'basic_auth'"
- )
- if isinstance(http_auth, str) or (
- isinstance(resolved_http_auth, (list, tuple))
- and all(isinstance(x, str) for x in resolved_http_auth)
- ):
- resolved_basic_auth = resolved_http_auth
- else:
- raise TypeError(
- "The deprecated 'http_auth' parameter must be either 'Tuple[str, str]' or 'str'. "
- "Use either the 'basic_auth' parameter instead"
- )
-
- warnings.warn(
- "The 'http_auth' parameter is deprecated. "
- "Use 'basic_auth' or 'bearer_auth' parameters instead",
- category=DeprecationWarning,
- stacklevel=warn_stacklevel(),
- )
-
resolved_api_key = api_key if api_key is not DEFAULT else None
resolved_bearer_auth = bearer_auth if bearer_auth is not DEFAULT else None
if resolved_api_key or resolved_basic_auth or resolved_bearer_auth:
diff --git a/elasticsearch/_sync/client/utils.py b/elasticsearch/_sync/client/utils.py
index 48ebcb217..3293e356e 100644
--- a/elasticsearch/_sync/client/utils.py
+++ b/elasticsearch/_sync/client/utils.py
@@ -16,7 +16,6 @@
# under the License.
import base64
-import inspect
import urllib.parse
import warnings
from datetime import date, datetime
@@ -44,7 +43,6 @@
AsyncTransport,
HttpHeaders,
NodeConfig,
- RequestsHttpNode,
SniffOptions,
Transport,
)
@@ -92,7 +90,6 @@ class Stability(Enum):
_TRANSPORT_OPTIONS = {
"api_key",
- "http_auth",
"request_timeout",
"opaque_id",
"headers",
@@ -105,7 +102,6 @@ class Stability(Enum):
def client_node_configs(
hosts: Optional[_TYPE_HOSTS],
cloud_id: Optional[str],
- requests_session_auth: Optional[Any] = None,
**kwargs: Any,
) -> List[NodeConfig]:
if cloud_id is not None:
@@ -126,12 +122,6 @@ def client_node_configs(
headers.setdefault("user-agent", USER_AGENT)
node_options["headers"] = headers
- # If a custom Requests AuthBase is passed we set that via '_extras'.
- if requests_session_auth is not None:
- node_options.setdefault("_extras", {})[
- "requests.session.auth"
- ] = requests_session_auth
-
def apply_node_options(node_config: NodeConfig) -> NodeConfig:
"""Needs special handling of headers since .replace() wipes out existing headers"""
headers = node_config.headers.copy() # type: ignore[attr-defined]
@@ -448,28 +438,3 @@ def wrapped(*args: Any, **kwargs: Any) -> Any:
return wrapped # type: ignore[return-value]
return wrapper
-
-
-def is_requests_http_auth(http_auth: Any) -> bool:
- """Detect if an http_auth value is a custom Requests auth object"""
- try:
- from requests.auth import AuthBase
-
- return isinstance(http_auth, AuthBase)
- except ImportError:
- pass
- return False
-
-
-def is_requests_node_class(node_class: Any) -> bool:
- """Detect if 'RequestsHttpNode' would be used given the setting of 'node_class'"""
- return (
- node_class is not None
- and node_class is not DEFAULT
- and (
- node_class == "requests"
- or (
- inspect.isclass(node_class) and issubclass(node_class, RequestsHttpNode)
- )
- )
- )
diff --git a/elasticsearch/helpers/actions.py b/elasticsearch/helpers/actions.py
index d1a43a8dc..25c21cdd4 100644
--- a/elasticsearch/helpers/actions.py
+++ b/elasticsearch/helpers/actions.py
@@ -698,16 +698,12 @@ def pop_transport_kwargs(kw: MutableMapping[str, Any]) -> Dict[str, Any]:
for key in (
"headers",
"api_key",
- "http_auth",
"basic_auth",
"bearer_auth",
"opaque_id",
):
try:
- value = kw.pop(key)
- if key == "http_auth":
- key = "basic_auth"
- transport_kwargs[key] = value
+ transport_kwargs[key] = kw.pop(key)
except KeyError:
pass
return transport_kwargs
diff --git a/test_elasticsearch/test_async/test_server/test_helpers.py b/test_elasticsearch/test_async/test_server/test_helpers.py
index 0bb781304..86439b487 100644
--- a/test_elasticsearch/test_async/test_server/test_helpers.py
+++ b/test_elasticsearch/test_async/test_server/test_helpers.py
@@ -741,7 +741,8 @@ async def test_clear_scroll(self, async_client, scan_teardown):
"kwargs",
[
{"api_key": ("name", "value")},
- {"http_auth": ("username", "password")},
+ {"basic_auth": ("username", "password")},
+ {"bearer_auth": "token"},
{"headers": {"custom", "header"}},
],
)
@@ -790,9 +791,6 @@ async def test_scan_auth_kwargs_forwarded(
assert data == [{"search_data": 1}]
- if "http_auth" in kwargs:
- kwargs = {"basic_auth": kwargs.pop("http_auth")}
-
assert options.call_args_list == [
call(request_timeout=None, **kwargs),
call(ignore_status=404),
diff --git a/test_elasticsearch/test_client/test_deprecated_options.py b/test_elasticsearch/test_client/test_deprecated_options.py
index 3b4e0b9ed..a4db1fbb7 100644
--- a/test_elasticsearch/test_client/test_deprecated_options.py
+++ b/test_elasticsearch/test_client/test_deprecated_options.py
@@ -100,32 +100,6 @@ def test_randomize_hosts():
)
-def test_http_auth():
- with warnings.catch_warnings(record=True) as w:
- client = Elasticsearch(
- "http://localhost:9200", http_auth=("username", "password")
- )
-
- assert len(w) == 1
- assert w[0].category == DeprecationWarning
- assert (
- str(w[0].message)
- == "The 'http_auth' parameter is deprecated. Use 'basic_auth' or 'bearer_auth' parameters instead"
- )
- assert client._headers["Authorization"] == "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
-
- with pytest.raises(ValueError) as e:
- Elasticsearch(
- "http://localhost:9200",
- http_auth=("username", "password"),
- basic_auth=("username", "password"),
- )
- assert (
- str(e.value)
- == "Can't specify both 'http_auth' and 'basic_auth', instead only specify 'basic_auth'"
- )
-
-
def test_serializer_and_serializers():
with pytest.raises(ValueError) as e:
Elasticsearch(
diff --git a/test_elasticsearch/test_client/test_requests_auth.py b/test_elasticsearch/test_client/test_requests_auth.py
deleted file mode 100644
index 2eb656f5d..000000000
--- a/test_elasticsearch/test_client/test_requests_auth.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# Licensed to Elasticsearch B.V. under one or more contributor
-# license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright
-# ownership. Elasticsearch B.V. licenses this file to you under
-# the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import warnings
-
-import pytest
-import requests
-from elastic_transport import RequestsHttpNode, Urllib3HttpNode
-from elastic_transport.client_utils import DEFAULT
-from requests.auth import HTTPBasicAuth
-
-from elasticsearch import AsyncElasticsearch, Elasticsearch
-
-
-class CustomRequestHttpNode(RequestsHttpNode):
- pass
-
-
-class CustomUrllib3HttpNode(Urllib3HttpNode):
- pass
-
-
-@pytest.mark.parametrize(
- "node_class", ["requests", RequestsHttpNode, CustomRequestHttpNode]
-)
-def test_requests_auth(node_class):
- http_auth = HTTPBasicAuth("username", "password")
-
- with warnings.catch_warnings(record=True) as w:
- client = Elasticsearch(
- "http://localhost:9200", http_auth=http_auth, node_class=node_class
- )
-
- # http_auth is deprecated for all other cases except this one.
- assert len(w) == 0
-
- # Instance should be forwarded directly to requests.Session.auth.
- node = client.transport.node_pool.get()
- assert isinstance(node, RequestsHttpNode)
- assert isinstance(node.session, requests.Session)
- assert node.session.auth is http_auth
-
-
-@pytest.mark.parametrize("client_class", [Elasticsearch, AsyncElasticsearch])
-@pytest.mark.parametrize(
- "node_class", ["urllib3", "aiohttp", None, DEFAULT, CustomUrllib3HttpNode]
-)
-def test_error_for_requests_auth_node_class(client_class, node_class):
- http_auth = HTTPBasicAuth("username", "password")
-
- with pytest.raises(ValueError) as e:
- client_class(
- "http://localhost:9200", http_auth=http_auth, node_class=node_class
- )
- assert str(e.value) == (
- "Using a custom 'requests.auth.AuthBase' class for "
- "'http_auth' must be used with node_class='requests'"
- )
-
-
-def test_error_for_requests_auth_async():
- http_auth = HTTPBasicAuth("username", "password")
-
- with pytest.raises(ValueError) as e:
- AsyncElasticsearch(
- "http://localhost:9200", http_auth=http_auth, node_class="requests"
- )
- assert str(e.value) == (
- "Specified 'node_class' is not async, should be async instead"
- )
diff --git a/test_elasticsearch/test_client/test_rewrite_parameters.py b/test_elasticsearch/test_client/test_rewrite_parameters.py
index 50a232563..f933cfd51 100644
--- a/test_elasticsearch/test_client/test_rewrite_parameters.py
+++ b/test_elasticsearch/test_client/test_rewrite_parameters.py
@@ -208,7 +208,7 @@ def test_ignore_deprecated_options(self):
body={"query": {"match_all": {}}},
params={"key": "value"},
param=1,
- http_auth=("key", "value"),
+ request_timeout=10,
)
assert len(w) == 1
@@ -219,7 +219,7 @@ def test_ignore_deprecated_options(self):
)
assert self.calls == [
- ((), {"http_auth": ("key", "value")}),
+ ((), {"request_timeout": 10}),
(
(),
{
diff --git a/test_elasticsearch/test_server/test_helpers.py b/test_elasticsearch/test_server/test_helpers.py
index 6ed43e2af..361a98ae2 100644
--- a/test_elasticsearch/test_server/test_helpers.py
+++ b/test_elasticsearch/test_server/test_helpers.py
@@ -626,7 +626,6 @@ def test_no_scroll_id_fast_route(sync_client):
"kwargs",
[
{"api_key": ("name", "value")},
- {"http_auth": ("username", "password")},
{"basic_auth": ("username", "password")},
{"bearer_auth": "token"},
{"headers": {"custom", "header"}},
@@ -634,8 +633,6 @@ def test_no_scroll_id_fast_route(sync_client):
)
@pytest.mark.usefixtures("scan_teardown")
def test_scan_auth_kwargs_forwarded(sync_client, kwargs):
- ((key, val),) = kwargs.items()
-
with patch.object(
sync_client, "options", return_value=sync_client
) as options, patch.object(
@@ -668,9 +665,7 @@ def test_scan_auth_kwargs_forwarded(sync_client, kwargs):
assert data == [{"search_data": 1}]
assert options.call_args_list == [
- call(
- request_timeout=None, **{key if key != "http_auth" else "basic_auth": val}
- ),
+ call(request_timeout=None, **kwargs),
call(ignore_status=404),
]
From 961dd2b60156ef83cdb3261e369545dd78f83e3b Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 2 Apr 2025 15:45:02 +0100
Subject: [PATCH 13/57] Remove deprecated Elasticsearch() options (#2840)
(#2876)
(cherry picked from commit 20e09c303f14319a6fb085823fe72b9aa21905ac)
Co-authored-by: Quentin Pradet
---
elasticsearch/_async/client/__init__.py | 94 +-----------
elasticsearch/_sync/client/__init__.py | 94 +-----------
.../test_async/test_transport.py | 40 +----
.../test_client/test_deprecated_options.py | 137 ------------------
.../test_client/test_options.py | 56 ++++++-
test_elasticsearch/test_transport.py | 39 +----
.../test_types/aliased_types.py | 4 -
test_elasticsearch/test_types/async_types.py | 2 -
test_elasticsearch/test_types/sync_types.py | 2 -
9 files changed, 59 insertions(+), 409 deletions(-)
delete mode 100644 test_elasticsearch/test_client/test_deprecated_options.py
diff --git a/elasticsearch/_async/client/__init__.py b/elasticsearch/_async/client/__init__.py
index 14ada0e22..243a71401 100644
--- a/elasticsearch/_async/client/__init__.py
+++ b/elasticsearch/_async/client/__init__.py
@@ -18,7 +18,6 @@
import logging
import typing as t
-import warnings
from elastic_transport import (
AsyncTransport,
@@ -179,36 +178,12 @@ def __init__(
t.Callable[[t.Dict[str, t.Any], NodeConfig], t.Optional[NodeConfig]]
] = None,
meta_header: t.Union[DefaultType, bool] = DEFAULT,
- timeout: t.Union[DefaultType, None, float] = DEFAULT,
- randomize_hosts: t.Union[DefaultType, bool] = DEFAULT,
- host_info_callback: t.Optional[
- t.Callable[
- [t.Dict[str, t.Any], t.Dict[str, t.Union[str, int]]],
- t.Optional[t.Dict[str, t.Union[str, int]]],
- ]
- ] = None,
- sniffer_timeout: t.Union[DefaultType, None, float] = DEFAULT,
- sniff_on_connection_fail: t.Union[DefaultType, bool] = DEFAULT,
- maxsize: t.Union[DefaultType, int] = DEFAULT,
# Internal use only
_transport: t.Optional[AsyncTransport] = None,
) -> None:
if hosts is None and cloud_id is None and _transport is None:
raise ValueError("Either 'hosts' or 'cloud_id' must be specified")
- if timeout is not DEFAULT:
- if request_timeout is not DEFAULT:
- raise ValueError(
- "Can't specify both 'timeout' and 'request_timeout', "
- "instead only specify 'request_timeout'"
- )
- warnings.warn(
- "The 'timeout' parameter is deprecated in favor of 'request_timeout'",
- category=DeprecationWarning,
- stacklevel=2,
- )
- request_timeout = timeout
-
if serializer is not None:
if serializers is not DEFAULT:
raise ValueError(
@@ -217,58 +192,6 @@ def __init__(
)
serializers = {default_mimetype: serializer}
- if randomize_hosts is not DEFAULT:
- if randomize_nodes_in_pool is not DEFAULT:
- raise ValueError(
- "Can't specify both 'randomize_hosts' and 'randomize_nodes_in_pool', "
- "instead only specify 'randomize_nodes_in_pool'"
- )
- warnings.warn(
- "The 'randomize_hosts' parameter is deprecated in favor of 'randomize_nodes_in_pool'",
- category=DeprecationWarning,
- stacklevel=2,
- )
- randomize_nodes_in_pool = randomize_hosts
-
- if sniffer_timeout is not DEFAULT:
- if min_delay_between_sniffing is not DEFAULT:
- raise ValueError(
- "Can't specify both 'sniffer_timeout' and 'min_delay_between_sniffing', "
- "instead only specify 'min_delay_between_sniffing'"
- )
- warnings.warn(
- "The 'sniffer_timeout' parameter is deprecated in favor of 'min_delay_between_sniffing'",
- category=DeprecationWarning,
- stacklevel=2,
- )
- min_delay_between_sniffing = sniffer_timeout
-
- if sniff_on_connection_fail is not DEFAULT:
- if sniff_on_node_failure is not DEFAULT:
- raise ValueError(
- "Can't specify both 'sniff_on_connection_fail' and 'sniff_on_node_failure', "
- "instead only specify 'sniff_on_node_failure'"
- )
- warnings.warn(
- "The 'sniff_on_connection_fail' parameter is deprecated in favor of 'sniff_on_node_failure'",
- category=DeprecationWarning,
- stacklevel=2,
- )
- sniff_on_node_failure = sniff_on_connection_fail
-
- if maxsize is not DEFAULT:
- if connections_per_node is not DEFAULT:
- raise ValueError(
- "Can't specify both 'maxsize' and 'connections_per_node', "
- "instead only specify 'connections_per_node'"
- )
- warnings.warn(
- "The 'maxsize' parameter is deprecated in favor of 'connections_per_node'",
- category=DeprecationWarning,
- stacklevel=2,
- )
- connections_per_node = maxsize
-
# Setting min_delay_between_sniffing=True implies sniff_before_requests=True
if min_delay_between_sniffing is not DEFAULT:
sniff_before_requests = True
@@ -290,22 +213,7 @@ def __init__(
)
sniff_callback = None
- if host_info_callback is not None:
- if sniffed_node_callback is not None:
- raise ValueError(
- "Can't specify both 'host_info_callback' and 'sniffed_node_callback', "
- "instead only specify 'sniffed_node_callback'"
- )
- warnings.warn(
- "The 'host_info_callback' parameter is deprecated in favor of 'sniffed_node_callback'",
- category=DeprecationWarning,
- stacklevel=2,
- )
-
- sniff_callback = create_sniff_callback(
- host_info_callback=host_info_callback
- )
- elif sniffed_node_callback is not None:
+ if sniffed_node_callback is not None:
sniff_callback = create_sniff_callback(
sniffed_node_callback=sniffed_node_callback
)
diff --git a/elasticsearch/_sync/client/__init__.py b/elasticsearch/_sync/client/__init__.py
index 46484630a..3a4435ce9 100644
--- a/elasticsearch/_sync/client/__init__.py
+++ b/elasticsearch/_sync/client/__init__.py
@@ -18,7 +18,6 @@
import logging
import typing as t
-import warnings
from elastic_transport import (
BaseNode,
@@ -179,36 +178,12 @@ def __init__(
t.Callable[[t.Dict[str, t.Any], NodeConfig], t.Optional[NodeConfig]]
] = None,
meta_header: t.Union[DefaultType, bool] = DEFAULT,
- timeout: t.Union[DefaultType, None, float] = DEFAULT,
- randomize_hosts: t.Union[DefaultType, bool] = DEFAULT,
- host_info_callback: t.Optional[
- t.Callable[
- [t.Dict[str, t.Any], t.Dict[str, t.Union[str, int]]],
- t.Optional[t.Dict[str, t.Union[str, int]]],
- ]
- ] = None,
- sniffer_timeout: t.Union[DefaultType, None, float] = DEFAULT,
- sniff_on_connection_fail: t.Union[DefaultType, bool] = DEFAULT,
- maxsize: t.Union[DefaultType, int] = DEFAULT,
# Internal use only
_transport: t.Optional[Transport] = None,
) -> None:
if hosts is None and cloud_id is None and _transport is None:
raise ValueError("Either 'hosts' or 'cloud_id' must be specified")
- if timeout is not DEFAULT:
- if request_timeout is not DEFAULT:
- raise ValueError(
- "Can't specify both 'timeout' and 'request_timeout', "
- "instead only specify 'request_timeout'"
- )
- warnings.warn(
- "The 'timeout' parameter is deprecated in favor of 'request_timeout'",
- category=DeprecationWarning,
- stacklevel=2,
- )
- request_timeout = timeout
-
if serializer is not None:
if serializers is not DEFAULT:
raise ValueError(
@@ -217,58 +192,6 @@ def __init__(
)
serializers = {default_mimetype: serializer}
- if randomize_hosts is not DEFAULT:
- if randomize_nodes_in_pool is not DEFAULT:
- raise ValueError(
- "Can't specify both 'randomize_hosts' and 'randomize_nodes_in_pool', "
- "instead only specify 'randomize_nodes_in_pool'"
- )
- warnings.warn(
- "The 'randomize_hosts' parameter is deprecated in favor of 'randomize_nodes_in_pool'",
- category=DeprecationWarning,
- stacklevel=2,
- )
- randomize_nodes_in_pool = randomize_hosts
-
- if sniffer_timeout is not DEFAULT:
- if min_delay_between_sniffing is not DEFAULT:
- raise ValueError(
- "Can't specify both 'sniffer_timeout' and 'min_delay_between_sniffing', "
- "instead only specify 'min_delay_between_sniffing'"
- )
- warnings.warn(
- "The 'sniffer_timeout' parameter is deprecated in favor of 'min_delay_between_sniffing'",
- category=DeprecationWarning,
- stacklevel=2,
- )
- min_delay_between_sniffing = sniffer_timeout
-
- if sniff_on_connection_fail is not DEFAULT:
- if sniff_on_node_failure is not DEFAULT:
- raise ValueError(
- "Can't specify both 'sniff_on_connection_fail' and 'sniff_on_node_failure', "
- "instead only specify 'sniff_on_node_failure'"
- )
- warnings.warn(
- "The 'sniff_on_connection_fail' parameter is deprecated in favor of 'sniff_on_node_failure'",
- category=DeprecationWarning,
- stacklevel=2,
- )
- sniff_on_node_failure = sniff_on_connection_fail
-
- if maxsize is not DEFAULT:
- if connections_per_node is not DEFAULT:
- raise ValueError(
- "Can't specify both 'maxsize' and 'connections_per_node', "
- "instead only specify 'connections_per_node'"
- )
- warnings.warn(
- "The 'maxsize' parameter is deprecated in favor of 'connections_per_node'",
- category=DeprecationWarning,
- stacklevel=2,
- )
- connections_per_node = maxsize
-
# Setting min_delay_between_sniffing=True implies sniff_before_requests=True
if min_delay_between_sniffing is not DEFAULT:
sniff_before_requests = True
@@ -290,22 +213,7 @@ def __init__(
)
sniff_callback = None
- if host_info_callback is not None:
- if sniffed_node_callback is not None:
- raise ValueError(
- "Can't specify both 'host_info_callback' and 'sniffed_node_callback', "
- "instead only specify 'sniffed_node_callback'"
- )
- warnings.warn(
- "The 'host_info_callback' parameter is deprecated in favor of 'sniffed_node_callback'",
- category=DeprecationWarning,
- stacklevel=2,
- )
-
- sniff_callback = create_sniff_callback(
- host_info_callback=host_info_callback
- )
- elif sniffed_node_callback is not None:
+ if sniffed_node_callback is not None:
sniff_callback = create_sniff_callback(
sniffed_node_callback=sniffed_node_callback
)
diff --git a/test_elasticsearch/test_async/test_transport.py b/test_elasticsearch/test_async/test_transport.py
index 76a71f50b..baebc0671 100644
--- a/test_elasticsearch/test_async/test_transport.py
+++ b/test_elasticsearch/test_async/test_transport.py
@@ -19,7 +19,7 @@
import asyncio
import re
import warnings
-from typing import Any, Dict, Optional, Union
+from typing import Any, Dict, Optional
import pytest
from elastic_transport import (
@@ -562,10 +562,8 @@ async def test_sniff_after_n_seconds(self, event_loop):
"kwargs",
[
{"sniff_on_start": True},
- {"sniff_on_connection_fail": True},
{"sniff_on_node_failure": True},
{"sniff_before_requests": True},
- {"sniffer_timeout": 1},
{"sniff_timeout": 1},
],
)
@@ -660,42 +658,6 @@ def sniffed_node_callback(
ports = {node.config.port for node in client.transport.node_pool.all()}
assert ports == {9200, 124}
- async def test_sniffing_deprecated_host_info_callback(self):
- def host_info_callback(
- node_info: Dict[str, Any], host: Dict[str, Union[int, str]]
- ) -> Dict[str, Any]:
- return (
- host if node_info["http"]["publish_address"].endswith(":124") else None
- )
-
- with warnings.catch_warnings(record=True) as w:
- client = AsyncElasticsearch( # noqa: F821
- [
- NodeConfig(
- "http",
- "localhost",
- 9200,
- _extras={"data": CLUSTER_NODES_MASTER_ONLY},
- )
- ],
- node_class=DummyNode,
- sniff_on_start=True,
- host_info_callback=host_info_callback,
- )
- await client.transport._async_call()
-
- assert len(w) == 1
- assert w[0].category == DeprecationWarning
- assert (
- str(w[0].message)
- == "The 'host_info_callback' parameter is deprecated in favor of 'sniffed_node_callback'"
- )
-
- assert len(client.transport.node_pool) == 2
-
- ports = {node.config.port for node in client.transport.node_pool.all()}
- assert ports == {9200, 124}
-
@pytest.mark.parametrize("headers", [{}, {"X-elastic-product": "BAD HEADER"}])
async def test_unsupported_product_error(headers):
diff --git a/test_elasticsearch/test_client/test_deprecated_options.py b/test_elasticsearch/test_client/test_deprecated_options.py
deleted file mode 100644
index a4db1fbb7..000000000
--- a/test_elasticsearch/test_client/test_deprecated_options.py
+++ /dev/null
@@ -1,137 +0,0 @@
-# Licensed to Elasticsearch B.V. under one or more contributor
-# license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright
-# ownership. Elasticsearch B.V. licenses this file to you under
-# the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import warnings
-
-import pytest
-
-from elasticsearch import Elasticsearch, JsonSerializer
-
-EXPECTED_SERIALIZERS = {
- "application/vnd.mapbox-vector-tile",
- "application/x-ndjson",
- "application/json",
- "text/*",
- "application/vnd.elasticsearch+json",
- "application/vnd.elasticsearch+x-ndjson",
-}
-
-
-try:
- import pyarrow as pa
-
- EXPECTED_SERIALIZERS.add("application/vnd.apache.arrow.stream")
-except ImportError:
- pa = None
-
-
-def test_sniff_on_connection_fail():
- with warnings.catch_warnings(record=True) as w:
- client = Elasticsearch("http://localhost:9200", sniff_on_connection_fail=True)
- assert client.transport._sniff_on_node_failure is True
- assert len(w) == 1
- assert w[0].category == DeprecationWarning
- assert str(w[0].message) == (
- "The 'sniff_on_connection_fail' parameter is deprecated in favor of 'sniff_on_node_failure'"
- )
-
- with pytest.raises(ValueError) as e:
- Elasticsearch(
- "http://localhost:9200",
- sniff_on_connection_fail=True,
- sniff_on_node_failure=True,
- )
- assert (
- str(e.value)
- == "Can't specify both 'sniff_on_connection_fail' and 'sniff_on_node_failure', instead only specify 'sniff_on_node_failure'"
- )
-
-
-def test_sniffer_timeout():
- with warnings.catch_warnings(record=True) as w:
- client = Elasticsearch("http://localhost:9200", sniffer_timeout=1)
- assert client.transport._min_delay_between_sniffing == 1
- assert len(w) == 1
- assert w[0].category == DeprecationWarning
- assert str(w[0].message) == (
- "The 'sniffer_timeout' parameter is deprecated in favor of 'min_delay_between_sniffing'"
- )
-
- with pytest.raises(ValueError) as e:
- Elasticsearch(
- "http://localhost:9200", sniffer_timeout=1, min_delay_between_sniffing=1
- )
- assert (
- str(e.value)
- == "Can't specify both 'sniffer_timeout' and 'min_delay_between_sniffing', instead only specify 'min_delay_between_sniffing'"
- )
-
-
-def test_randomize_hosts():
- with warnings.catch_warnings(record=True) as w:
- Elasticsearch("http://localhost:9200", randomize_hosts=True)
- assert len(w) == 1
- assert w[0].category == DeprecationWarning
- assert str(w[0].message) == (
- "The 'randomize_hosts' parameter is deprecated in favor of 'randomize_nodes_in_pool'"
- )
-
- with pytest.raises(ValueError) as e:
- Elasticsearch(
- "http://localhost:9200", randomize_hosts=True, randomize_nodes_in_pool=True
- )
- assert (
- str(e.value)
- == "Can't specify both 'randomize_hosts' and 'randomize_nodes_in_pool', instead only specify 'randomize_nodes_in_pool'"
- )
-
-
-def test_serializer_and_serializers():
- with pytest.raises(ValueError) as e:
- Elasticsearch(
- "http://localhost:9200",
- serializer=JsonSerializer(),
- serializers={"application/json": JsonSerializer()},
- )
- assert str(e.value) == (
- "Can't specify both 'serializer' and 'serializers' parameters together. "
- "Instead only specify one of the other."
- )
-
- class CustomSerializer(JsonSerializer):
- pass
-
- client = Elasticsearch("http://localhost:9200", serializer=CustomSerializer())
- assert isinstance(
- client.transport.serializers.get_serializer("application/json"),
- CustomSerializer,
- )
- assert set(client.transport.serializers.serializers.keys()) == EXPECTED_SERIALIZERS
-
- client = Elasticsearch(
- "http://localhost:9200",
- serializers={
- "application/json": CustomSerializer(),
- "application/cbor": CustomSerializer(),
- },
- )
- assert isinstance(
- client.transport.serializers.get_serializer("application/json"),
- CustomSerializer,
- )
- expected = EXPECTED_SERIALIZERS | {"application/cbor"}
- assert set(client.transport.serializers.serializers.keys()) == expected
diff --git a/test_elasticsearch/test_client/test_options.py b/test_elasticsearch/test_client/test_options.py
index b7fa3cfda..c2050d186 100644
--- a/test_elasticsearch/test_client/test_options.py
+++ b/test_elasticsearch/test_client/test_options.py
@@ -19,7 +19,7 @@
from elastic_transport import OpenTelemetrySpan
from elastic_transport.client_utils import DEFAULT
-from elasticsearch import AsyncElasticsearch, Elasticsearch
+from elasticsearch import AsyncElasticsearch, Elasticsearch, JsonSerializer
from elasticsearch._sync.client.utils import USER_AGENT
from test_elasticsearch.test_cases import (
DummyAsyncTransport,
@@ -27,6 +27,22 @@
DummyTransportTestCase,
)
+EXPECTED_SERIALIZERS = {
+ "application/vnd.mapbox-vector-tile",
+ "application/x-ndjson",
+ "application/json",
+ "text/*",
+ "application/vnd.elasticsearch+json",
+ "application/vnd.elasticsearch+x-ndjson",
+}
+
+try:
+ import pyarrow as pa
+
+ EXPECTED_SERIALIZERS.add("application/vnd.apache.arrow.stream")
+except ImportError:
+ pa = None
+
class TestOptions(DummyTransportTestCase):
def assert_called_with_headers(self, client, method, target, headers):
@@ -479,3 +495,41 @@ def test_options_timeout_parameters(self):
"retry_on_status": (404,),
"retry_on_timeout": True,
}
+
+ def test_serializer_and_serializers(self):
+ with pytest.raises(ValueError) as e:
+ Elasticsearch(
+ "http://localhost:9200",
+ serializer=JsonSerializer(),
+ serializers={"application/json": JsonSerializer()},
+ )
+ assert str(e.value) == (
+ "Can't specify both 'serializer' and 'serializers' parameters together. "
+ "Instead only specify one of the other."
+ )
+
+ class CustomSerializer(JsonSerializer):
+ pass
+
+ client = Elasticsearch("http://localhost:9200", serializer=CustomSerializer())
+ assert isinstance(
+ client.transport.serializers.get_serializer("application/json"),
+ CustomSerializer,
+ )
+ assert (
+ set(client.transport.serializers.serializers.keys()) == EXPECTED_SERIALIZERS
+ )
+
+ client = Elasticsearch(
+ "http://localhost:9200",
+ serializers={
+ "application/json": CustomSerializer(),
+ "application/cbor": CustomSerializer(),
+ },
+ )
+ assert isinstance(
+ client.transport.serializers.get_serializer("application/json"),
+ CustomSerializer,
+ )
+ expected = EXPECTED_SERIALIZERS | {"application/cbor"}
+ assert set(client.transport.serializers.serializers.keys()) == expected
diff --git a/test_elasticsearch/test_transport.py b/test_elasticsearch/test_transport.py
index 5161cd8e1..6fb72f98b 100644
--- a/test_elasticsearch/test_transport.py
+++ b/test_elasticsearch/test_transport.py
@@ -18,7 +18,7 @@
import re
import time
import warnings
-from typing import Any, Dict, Optional, Union
+from typing import Any, Dict, Optional
import pytest
from elastic_transport import (
@@ -525,10 +525,8 @@ def test_sniff_after_n_seconds(self):
"kwargs",
[
{"sniff_on_start": True},
- {"sniff_on_connection_fail": True},
{"sniff_on_node_failure": True},
{"sniff_before_requests": True},
- {"sniffer_timeout": 1},
{"sniff_timeout": 1},
],
)
@@ -589,41 +587,6 @@ def sniffed_node_callback(
ports = {node.config.port for node in client.transport.node_pool.all()}
assert ports == {9200, 124}
- def test_sniffing_deprecated_host_info_callback(self):
- def host_info_callback(
- node_info: Dict[str, Any], host: Dict[str, Union[int, str]]
- ) -> Dict[str, Any]:
- return (
- host if node_info["http"]["publish_address"].endswith(":124") else None
- )
-
- with warnings.catch_warnings(record=True) as w:
- client = Elasticsearch( # noqa: F821
- [
- NodeConfig(
- "http",
- "localhost",
- 9200,
- _extras={"data": CLUSTER_NODES_MASTER_ONLY},
- )
- ],
- node_class=DummyNode,
- sniff_on_start=True,
- host_info_callback=host_info_callback,
- )
-
- assert len(w) == 1
- assert w[0].category == DeprecationWarning
- assert (
- str(w[0].message)
- == "The 'host_info_callback' parameter is deprecated in favor of 'sniffed_node_callback'"
- )
-
- assert len(client.transport.node_pool) == 2
-
- ports = {node.config.port for node in client.transport.node_pool.all()}
- assert ports == {9200, 124}
-
@pytest.mark.parametrize("headers", [{}, {"X-elastic-product": "BAD HEADER"}])
def test_unsupported_product_error(headers):
diff --git a/test_elasticsearch/test_types/aliased_types.py b/test_elasticsearch/test_types/aliased_types.py
index 0b5c97f98..ff0aa994a 100644
--- a/test_elasticsearch/test_types/aliased_types.py
+++ b/test_elasticsearch/test_types/aliased_types.py
@@ -34,9 +34,7 @@
[{"host": "localhost", "port": 9443}],
transport_class=Transport,
sniff_on_start=True,
- sniffer_timeout=0.1,
sniff_timeout=1,
- sniff_on_connection_fail=False,
max_retries=1,
retry_on_status={100, 400, 503},
retry_on_timeout=True,
@@ -103,9 +101,7 @@ def reindex_types() -> None:
es2 = AsyncElasticsearch(
[{"host": "localhost", "port": 9443}],
sniff_on_start=True,
- sniffer_timeout=0.1,
sniff_timeout=1,
- sniff_on_connection_fail=False,
max_retries=1,
retry_on_status={100, 400, 503},
retry_on_timeout=True,
diff --git a/test_elasticsearch/test_types/async_types.py b/test_elasticsearch/test_types/async_types.py
index ac7eed19a..1743fde2d 100644
--- a/test_elasticsearch/test_types/async_types.py
+++ b/test_elasticsearch/test_types/async_types.py
@@ -28,9 +28,7 @@
es = AsyncElasticsearch(
[{"host": "localhost", "port": 9443}],
sniff_on_start=True,
- sniffer_timeout=0.1,
sniff_timeout=1,
- sniff_on_connection_fail=False,
max_retries=1,
retry_on_status={100, 400, 503},
retry_on_timeout=True,
diff --git a/test_elasticsearch/test_types/sync_types.py b/test_elasticsearch/test_types/sync_types.py
index f4582ddba..8166e50ee 100644
--- a/test_elasticsearch/test_types/sync_types.py
+++ b/test_elasticsearch/test_types/sync_types.py
@@ -23,9 +23,7 @@
es = Elasticsearch(
[{"host": "localhost", "port": 9443}],
sniff_on_start=True,
- sniffer_timeout=0.1,
sniff_timeout=1,
- sniff_on_connection_fail=False,
max_retries=1,
retry_on_status={100, 400, 503},
retry_on_timeout=True,
From b243ae161ca17c890f8f974433e799a8587ef968 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 2 Apr 2025 16:09:44 +0100
Subject: [PATCH 14/57] Revert "Remove deprecated http_auth parameter (#2839)"
(#2872) (#2877)
This reverts commit 74387d0a3f42517e2a5805c9bb0aec57511b6e15.
(cherry picked from commit d480a2f8d14ae5c91bef1ba4975e7fb0196556a6)
Co-authored-by: Miguel Grinberg
---
elasticsearch/_async/client/__init__.py | 21 +++++
elasticsearch/_async/client/_base.py | 26 ++++++
elasticsearch/_async/client/utils.py | 4 +
elasticsearch/_async/helpers.py | 7 +-
elasticsearch/_sync/client/__init__.py | 21 +++++
elasticsearch/_sync/client/_base.py | 26 ++++++
elasticsearch/_sync/client/utils.py | 35 ++++++++
elasticsearch/helpers/actions.py | 6 +-
.../test_async/test_server/test_helpers.py | 6 +-
.../test_client/test_deprecated_options.py | 48 +++++++++++
.../test_client/test_requests_auth.py | 84 +++++++++++++++++++
.../test_client/test_rewrite_parameters.py | 4 +-
.../test_server/test_helpers.py | 7 +-
13 files changed, 287 insertions(+), 8 deletions(-)
create mode 100644 test_elasticsearch/test_client/test_deprecated_options.py
create mode 100644 test_elasticsearch/test_client/test_requests_auth.py
diff --git a/elasticsearch/_async/client/__init__.py b/elasticsearch/_async/client/__init__.py
index 243a71401..d05ce7a1a 100644
--- a/elasticsearch/_async/client/__init__.py
+++ b/elasticsearch/_async/client/__init__.py
@@ -87,6 +87,8 @@
_rewrite_parameters,
_stability_warning,
client_node_configs,
+ is_requests_http_auth,
+ is_requests_node_class,
)
from .watcher import WatcherClient
from .xpack import XPackClient
@@ -178,6 +180,7 @@ def __init__(
t.Callable[[t.Dict[str, t.Any], NodeConfig], t.Optional[NodeConfig]]
] = None,
meta_header: t.Union[DefaultType, bool] = DEFAULT,
+ http_auth: t.Union[DefaultType, t.Any] = DEFAULT,
# Internal use only
_transport: t.Optional[AsyncTransport] = None,
) -> None:
@@ -225,9 +228,26 @@ def __init__(
sniff_callback = default_sniff_callback
if _transport is None:
+ requests_session_auth = None
+ if http_auth is not None and http_auth is not DEFAULT:
+ if is_requests_http_auth(http_auth):
+ # If we're using custom requests authentication
+ # then we need to alert the user that they also
+ # need to use 'node_class=requests'.
+ if not is_requests_node_class(node_class):
+ raise ValueError(
+ "Using a custom 'requests.auth.AuthBase' class for "
+ "'http_auth' must be used with node_class='requests'"
+ )
+
+ # Reset 'http_auth' to DEFAULT so it's not consumed below.
+ requests_session_auth = http_auth
+ http_auth = DEFAULT
+
node_configs = client_node_configs(
hosts,
cloud_id=cloud_id,
+ requests_session_auth=requests_session_auth,
connections_per_node=connections_per_node,
http_compress=http_compress,
verify_certs=verify_certs,
@@ -314,6 +334,7 @@ def __init__(
self._headers["x-opaque-id"] = opaque_id
self._headers = resolve_auth_headers(
self._headers,
+ http_auth=http_auth,
api_key=api_key,
basic_auth=basic_auth,
bearer_auth=bearer_auth,
diff --git a/elasticsearch/_async/client/_base.py b/elasticsearch/_async/client/_base.py
index 3907cfd84..cc090671c 100644
--- a/elasticsearch/_async/client/_base.py
+++ b/elasticsearch/_async/client/_base.py
@@ -68,6 +68,7 @@
def resolve_auth_headers(
headers: Optional[Mapping[str, str]],
+ http_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
api_key: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
basic_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
bearer_auth: Union[DefaultType, None, str] = DEFAULT,
@@ -77,7 +78,32 @@ def resolve_auth_headers(
elif not isinstance(headers, HttpHeaders):
headers = HttpHeaders(headers)
+ resolved_http_auth = http_auth if http_auth is not DEFAULT else None
resolved_basic_auth = basic_auth if basic_auth is not DEFAULT else None
+ if resolved_http_auth is not None:
+ if resolved_basic_auth is not None:
+ raise ValueError(
+ "Can't specify both 'http_auth' and 'basic_auth', "
+ "instead only specify 'basic_auth'"
+ )
+ if isinstance(http_auth, str) or (
+ isinstance(resolved_http_auth, (list, tuple))
+ and all(isinstance(x, str) for x in resolved_http_auth)
+ ):
+ resolved_basic_auth = resolved_http_auth
+ else:
+ raise TypeError(
+ "The deprecated 'http_auth' parameter must be either 'Tuple[str, str]' or 'str'. "
+ "Use either the 'basic_auth' parameter instead"
+ )
+
+ warnings.warn(
+ "The 'http_auth' parameter is deprecated. "
+ "Use 'basic_auth' or 'bearer_auth' parameters instead",
+ category=DeprecationWarning,
+ stacklevel=warn_stacklevel(),
+ )
+
resolved_api_key = api_key if api_key is not DEFAULT else None
resolved_bearer_auth = bearer_auth if bearer_auth is not DEFAULT else None
if resolved_api_key or resolved_basic_auth or resolved_bearer_auth:
diff --git a/elasticsearch/_async/client/utils.py b/elasticsearch/_async/client/utils.py
index ac7a35062..97918d9e4 100644
--- a/elasticsearch/_async/client/utils.py
+++ b/elasticsearch/_async/client/utils.py
@@ -27,6 +27,8 @@
_rewrite_parameters,
_stability_warning,
client_node_configs,
+ is_requests_http_auth,
+ is_requests_node_class,
)
__all__ = [
@@ -41,4 +43,6 @@
"client_node_configs",
"_rewrite_parameters",
"_stability_warning",
+ "is_requests_http_auth",
+ "is_requests_node_class",
]
diff --git a/elasticsearch/_async/helpers.py b/elasticsearch/_async/helpers.py
index 8b5d3d0d2..e4d5e6bc5 100644
--- a/elasticsearch/_async/helpers.py
+++ b/elasticsearch/_async/helpers.py
@@ -418,9 +418,12 @@ def pop_transport_kwargs(kw: MutableMapping[str, Any]) -> MutableMapping[str, An
# Grab options that should be propagated to every
# API call within this helper instead of just 'search()'
transport_kwargs = {}
- for key in ("headers", "api_key", "basic_auth", "bearer_auth"):
+ for key in ("headers", "api_key", "http_auth", "basic_auth", "bearer_auth"):
try:
- transport_kwargs[key] = kw.pop(key)
+ value = kw.pop(key)
+ if key == "http_auth":
+ key = "basic_auth"
+ transport_kwargs[key] = value
except KeyError:
pass
return transport_kwargs
diff --git a/elasticsearch/_sync/client/__init__.py b/elasticsearch/_sync/client/__init__.py
index 3a4435ce9..115a27a9a 100644
--- a/elasticsearch/_sync/client/__init__.py
+++ b/elasticsearch/_sync/client/__init__.py
@@ -87,6 +87,8 @@
_rewrite_parameters,
_stability_warning,
client_node_configs,
+ is_requests_http_auth,
+ is_requests_node_class,
)
from .watcher import WatcherClient
from .xpack import XPackClient
@@ -178,6 +180,7 @@ def __init__(
t.Callable[[t.Dict[str, t.Any], NodeConfig], t.Optional[NodeConfig]]
] = None,
meta_header: t.Union[DefaultType, bool] = DEFAULT,
+ http_auth: t.Union[DefaultType, t.Any] = DEFAULT,
# Internal use only
_transport: t.Optional[Transport] = None,
) -> None:
@@ -225,9 +228,26 @@ def __init__(
sniff_callback = default_sniff_callback
if _transport is None:
+ requests_session_auth = None
+ if http_auth is not None and http_auth is not DEFAULT:
+ if is_requests_http_auth(http_auth):
+ # If we're using custom requests authentication
+ # then we need to alert the user that they also
+ # need to use 'node_class=requests'.
+ if not is_requests_node_class(node_class):
+ raise ValueError(
+ "Using a custom 'requests.auth.AuthBase' class for "
+ "'http_auth' must be used with node_class='requests'"
+ )
+
+ # Reset 'http_auth' to DEFAULT so it's not consumed below.
+ requests_session_auth = http_auth
+ http_auth = DEFAULT
+
node_configs = client_node_configs(
hosts,
cloud_id=cloud_id,
+ requests_session_auth=requests_session_auth,
connections_per_node=connections_per_node,
http_compress=http_compress,
verify_certs=verify_certs,
@@ -314,6 +334,7 @@ def __init__(
self._headers["x-opaque-id"] = opaque_id
self._headers = resolve_auth_headers(
self._headers,
+ http_auth=http_auth,
api_key=api_key,
basic_auth=basic_auth,
bearer_auth=bearer_auth,
diff --git a/elasticsearch/_sync/client/_base.py b/elasticsearch/_sync/client/_base.py
index 64abdc250..868b71073 100644
--- a/elasticsearch/_sync/client/_base.py
+++ b/elasticsearch/_sync/client/_base.py
@@ -68,6 +68,7 @@
def resolve_auth_headers(
headers: Optional[Mapping[str, str]],
+ http_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
api_key: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
basic_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
bearer_auth: Union[DefaultType, None, str] = DEFAULT,
@@ -77,7 +78,32 @@ def resolve_auth_headers(
elif not isinstance(headers, HttpHeaders):
headers = HttpHeaders(headers)
+ resolved_http_auth = http_auth if http_auth is not DEFAULT else None
resolved_basic_auth = basic_auth if basic_auth is not DEFAULT else None
+ if resolved_http_auth is not None:
+ if resolved_basic_auth is not None:
+ raise ValueError(
+ "Can't specify both 'http_auth' and 'basic_auth', "
+ "instead only specify 'basic_auth'"
+ )
+ if isinstance(http_auth, str) or (
+ isinstance(resolved_http_auth, (list, tuple))
+ and all(isinstance(x, str) for x in resolved_http_auth)
+ ):
+ resolved_basic_auth = resolved_http_auth
+ else:
+ raise TypeError(
+ "The deprecated 'http_auth' parameter must be either 'Tuple[str, str]' or 'str'. "
+ "Use either the 'basic_auth' parameter instead"
+ )
+
+ warnings.warn(
+ "The 'http_auth' parameter is deprecated. "
+ "Use 'basic_auth' or 'bearer_auth' parameters instead",
+ category=DeprecationWarning,
+ stacklevel=warn_stacklevel(),
+ )
+
resolved_api_key = api_key if api_key is not DEFAULT else None
resolved_bearer_auth = bearer_auth if bearer_auth is not DEFAULT else None
if resolved_api_key or resolved_basic_auth or resolved_bearer_auth:
diff --git a/elasticsearch/_sync/client/utils.py b/elasticsearch/_sync/client/utils.py
index 3293e356e..48ebcb217 100644
--- a/elasticsearch/_sync/client/utils.py
+++ b/elasticsearch/_sync/client/utils.py
@@ -16,6 +16,7 @@
# under the License.
import base64
+import inspect
import urllib.parse
import warnings
from datetime import date, datetime
@@ -43,6 +44,7 @@
AsyncTransport,
HttpHeaders,
NodeConfig,
+ RequestsHttpNode,
SniffOptions,
Transport,
)
@@ -90,6 +92,7 @@ class Stability(Enum):
_TRANSPORT_OPTIONS = {
"api_key",
+ "http_auth",
"request_timeout",
"opaque_id",
"headers",
@@ -102,6 +105,7 @@ class Stability(Enum):
def client_node_configs(
hosts: Optional[_TYPE_HOSTS],
cloud_id: Optional[str],
+ requests_session_auth: Optional[Any] = None,
**kwargs: Any,
) -> List[NodeConfig]:
if cloud_id is not None:
@@ -122,6 +126,12 @@ def client_node_configs(
headers.setdefault("user-agent", USER_AGENT)
node_options["headers"] = headers
+ # If a custom Requests AuthBase is passed we set that via '_extras'.
+ if requests_session_auth is not None:
+ node_options.setdefault("_extras", {})[
+ "requests.session.auth"
+ ] = requests_session_auth
+
def apply_node_options(node_config: NodeConfig) -> NodeConfig:
"""Needs special handling of headers since .replace() wipes out existing headers"""
headers = node_config.headers.copy() # type: ignore[attr-defined]
@@ -438,3 +448,28 @@ def wrapped(*args: Any, **kwargs: Any) -> Any:
return wrapped # type: ignore[return-value]
return wrapper
+
+
+def is_requests_http_auth(http_auth: Any) -> bool:
+ """Detect if an http_auth value is a custom Requests auth object"""
+ try:
+ from requests.auth import AuthBase
+
+ return isinstance(http_auth, AuthBase)
+ except ImportError:
+ pass
+ return False
+
+
+def is_requests_node_class(node_class: Any) -> bool:
+ """Detect if 'RequestsHttpNode' would be used given the setting of 'node_class'"""
+ return (
+ node_class is not None
+ and node_class is not DEFAULT
+ and (
+ node_class == "requests"
+ or (
+ inspect.isclass(node_class) and issubclass(node_class, RequestsHttpNode)
+ )
+ )
+ )
diff --git a/elasticsearch/helpers/actions.py b/elasticsearch/helpers/actions.py
index 25c21cdd4..d1a43a8dc 100644
--- a/elasticsearch/helpers/actions.py
+++ b/elasticsearch/helpers/actions.py
@@ -698,12 +698,16 @@ def pop_transport_kwargs(kw: MutableMapping[str, Any]) -> Dict[str, Any]:
for key in (
"headers",
"api_key",
+ "http_auth",
"basic_auth",
"bearer_auth",
"opaque_id",
):
try:
- transport_kwargs[key] = kw.pop(key)
+ value = kw.pop(key)
+ if key == "http_auth":
+ key = "basic_auth"
+ transport_kwargs[key] = value
except KeyError:
pass
return transport_kwargs
diff --git a/test_elasticsearch/test_async/test_server/test_helpers.py b/test_elasticsearch/test_async/test_server/test_helpers.py
index 86439b487..0bb781304 100644
--- a/test_elasticsearch/test_async/test_server/test_helpers.py
+++ b/test_elasticsearch/test_async/test_server/test_helpers.py
@@ -741,8 +741,7 @@ async def test_clear_scroll(self, async_client, scan_teardown):
"kwargs",
[
{"api_key": ("name", "value")},
- {"basic_auth": ("username", "password")},
- {"bearer_auth": "token"},
+ {"http_auth": ("username", "password")},
{"headers": {"custom", "header"}},
],
)
@@ -791,6 +790,9 @@ async def test_scan_auth_kwargs_forwarded(
assert data == [{"search_data": 1}]
+ if "http_auth" in kwargs:
+ kwargs = {"basic_auth": kwargs.pop("http_auth")}
+
assert options.call_args_list == [
call(request_timeout=None, **kwargs),
call(ignore_status=404),
diff --git a/test_elasticsearch/test_client/test_deprecated_options.py b/test_elasticsearch/test_client/test_deprecated_options.py
new file mode 100644
index 000000000..bbde2e90b
--- /dev/null
+++ b/test_elasticsearch/test_client/test_deprecated_options.py
@@ -0,0 +1,48 @@
+# Licensed to Elasticsearch B.V. under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Elasticsearch B.V. licenses this file to you under
+# the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import warnings
+
+import pytest
+
+from elasticsearch import Elasticsearch
+
+
+def test_http_auth():
+ with warnings.catch_warnings(record=True) as w:
+ client = Elasticsearch(
+ "http://localhost:9200", http_auth=("username", "password")
+ )
+
+ assert len(w) == 1
+ assert w[0].category == DeprecationWarning
+ assert (
+ str(w[0].message)
+ == "The 'http_auth' parameter is deprecated. Use 'basic_auth' or 'bearer_auth' parameters instead"
+ )
+ assert client._headers["Authorization"] == "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
+
+ with pytest.raises(ValueError) as e:
+ Elasticsearch(
+ "http://localhost:9200",
+ http_auth=("username", "password"),
+ basic_auth=("username", "password"),
+ )
+ assert (
+ str(e.value)
+ == "Can't specify both 'http_auth' and 'basic_auth', instead only specify 'basic_auth'"
+ )
diff --git a/test_elasticsearch/test_client/test_requests_auth.py b/test_elasticsearch/test_client/test_requests_auth.py
new file mode 100644
index 000000000..2eb656f5d
--- /dev/null
+++ b/test_elasticsearch/test_client/test_requests_auth.py
@@ -0,0 +1,84 @@
+# Licensed to Elasticsearch B.V. under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Elasticsearch B.V. licenses this file to you under
+# the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import warnings
+
+import pytest
+import requests
+from elastic_transport import RequestsHttpNode, Urllib3HttpNode
+from elastic_transport.client_utils import DEFAULT
+from requests.auth import HTTPBasicAuth
+
+from elasticsearch import AsyncElasticsearch, Elasticsearch
+
+
+class CustomRequestHttpNode(RequestsHttpNode):
+ pass
+
+
+class CustomUrllib3HttpNode(Urllib3HttpNode):
+ pass
+
+
+@pytest.mark.parametrize(
+ "node_class", ["requests", RequestsHttpNode, CustomRequestHttpNode]
+)
+def test_requests_auth(node_class):
+ http_auth = HTTPBasicAuth("username", "password")
+
+ with warnings.catch_warnings(record=True) as w:
+ client = Elasticsearch(
+ "http://localhost:9200", http_auth=http_auth, node_class=node_class
+ )
+
+ # http_auth is deprecated for all other cases except this one.
+ assert len(w) == 0
+
+ # Instance should be forwarded directly to requests.Session.auth.
+ node = client.transport.node_pool.get()
+ assert isinstance(node, RequestsHttpNode)
+ assert isinstance(node.session, requests.Session)
+ assert node.session.auth is http_auth
+
+
+@pytest.mark.parametrize("client_class", [Elasticsearch, AsyncElasticsearch])
+@pytest.mark.parametrize(
+ "node_class", ["urllib3", "aiohttp", None, DEFAULT, CustomUrllib3HttpNode]
+)
+def test_error_for_requests_auth_node_class(client_class, node_class):
+ http_auth = HTTPBasicAuth("username", "password")
+
+ with pytest.raises(ValueError) as e:
+ client_class(
+ "http://localhost:9200", http_auth=http_auth, node_class=node_class
+ )
+ assert str(e.value) == (
+ "Using a custom 'requests.auth.AuthBase' class for "
+ "'http_auth' must be used with node_class='requests'"
+ )
+
+
+def test_error_for_requests_auth_async():
+ http_auth = HTTPBasicAuth("username", "password")
+
+ with pytest.raises(ValueError) as e:
+ AsyncElasticsearch(
+ "http://localhost:9200", http_auth=http_auth, node_class="requests"
+ )
+ assert str(e.value) == (
+ "Specified 'node_class' is not async, should be async instead"
+ )
diff --git a/test_elasticsearch/test_client/test_rewrite_parameters.py b/test_elasticsearch/test_client/test_rewrite_parameters.py
index f933cfd51..50a232563 100644
--- a/test_elasticsearch/test_client/test_rewrite_parameters.py
+++ b/test_elasticsearch/test_client/test_rewrite_parameters.py
@@ -208,7 +208,7 @@ def test_ignore_deprecated_options(self):
body={"query": {"match_all": {}}},
params={"key": "value"},
param=1,
- request_timeout=10,
+ http_auth=("key", "value"),
)
assert len(w) == 1
@@ -219,7 +219,7 @@ def test_ignore_deprecated_options(self):
)
assert self.calls == [
- ((), {"request_timeout": 10}),
+ ((), {"http_auth": ("key", "value")}),
(
(),
{
diff --git a/test_elasticsearch/test_server/test_helpers.py b/test_elasticsearch/test_server/test_helpers.py
index 361a98ae2..6ed43e2af 100644
--- a/test_elasticsearch/test_server/test_helpers.py
+++ b/test_elasticsearch/test_server/test_helpers.py
@@ -626,6 +626,7 @@ def test_no_scroll_id_fast_route(sync_client):
"kwargs",
[
{"api_key": ("name", "value")},
+ {"http_auth": ("username", "password")},
{"basic_auth": ("username", "password")},
{"bearer_auth": "token"},
{"headers": {"custom", "header"}},
@@ -633,6 +634,8 @@ def test_no_scroll_id_fast_route(sync_client):
)
@pytest.mark.usefixtures("scan_teardown")
def test_scan_auth_kwargs_forwarded(sync_client, kwargs):
+ ((key, val),) = kwargs.items()
+
with patch.object(
sync_client, "options", return_value=sync_client
) as options, patch.object(
@@ -665,7 +668,9 @@ def test_scan_auth_kwargs_forwarded(sync_client, kwargs):
assert data == [{"search_data": 1}]
assert options.call_args_list == [
- call(request_timeout=None, **kwargs),
+ call(
+ request_timeout=None, **{key if key != "http_auth" else "basic_auth": val}
+ ),
call(ignore_status=404),
]
From 1edb8fc8728fa83497d3565d16c913ed9c1dabd1 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 2 Apr 2025 20:17:25 +0400
Subject: [PATCH 15/57] Add back inference.inference API (#2873) (#2881)
* Add back inference.inference API
This function was removed from the specification in favor of one API per
provider and task type, but the existing function was stable and widely used in
Python. Still, we mark it as deprecated to encourage users to migrate to the
new APIs.
* Fix lint
(cherry picked from commit eac539dcc301b6062716f1540dc0d1efe888671c)
Co-authored-by: Quentin Pradet
---
elasticsearch/_async/client/inference.py | 119 ++++++++++++++++++++++-
elasticsearch/_sync/client/inference.py | 119 ++++++++++++++++++++++-
elasticsearch/_sync/client/utils.py | 7 ++
3 files changed, 243 insertions(+), 2 deletions(-)
diff --git a/elasticsearch/_async/client/inference.py b/elasticsearch/_async/client/inference.py
index 73983f07a..31b371948 100644
--- a/elasticsearch/_async/client/inference.py
+++ b/elasticsearch/_async/client/inference.py
@@ -20,7 +20,13 @@
from elastic_transport import ObjectApiResponse
from ._base import NamespacedClient
-from .utils import SKIP_IN_PATH, _quote, _rewrite_parameters
+from .utils import (
+ SKIP_IN_PATH,
+ Stability,
+ _quote,
+ _rewrite_parameters,
+ _stability_warning,
+)
class InferenceClient(NamespacedClient):
@@ -234,6 +240,117 @@ async def get(
path_parts=__path_parts,
)
+ @_rewrite_parameters(
+ body_fields=("input", "query", "task_settings"),
+ )
+ @_stability_warning(
+ Stability.DEPRECATED,
+ version="8.18.0",
+ message="inference.inference() is deprecated in favor of provider-specific APIs such as inference.put_elasticsearch() or inference.put_hugging_face()",
+ )
+ async def inference(
+ self,
+ *,
+ inference_id: str,
+ input: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ task_type: t.Optional[
+ t.Union[
+ str,
+ t.Literal[
+ "chat_completion",
+ "completion",
+ "rerank",
+ "sparse_embedding",
+ "text_embedding",
+ ],
+ ]
+ ] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ query: t.Optional[str] = None,
+ task_settings: t.Optional[t.Any] = None,
+ timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Perform inference on the service.
+
This API enables you to use machine learning models to perform specific tasks on data that you provide as an input.
+ It returns a response with the results of the tasks.
+ The inference endpoint you use can perform one specific task that has been defined when the endpoint was created with the create inference API.
+
+
info
+ The inference APIs enable you to use certain services, such as built-in machine learning models (ELSER, E5), models uploaded through Eland, Cohere, OpenAI, Azure, Google AI Studio, Google Vertex AI, Anthropic, Watsonx.ai, or Hugging Face. For built-in models and models uploaded through Eland, the inference APIs offer an alternative way to use and manage trained models. However, if you do not plan to use the inference APIs to use these models or if you want to use non-NLP models, use the machine learning trained model APIs.
+
+
+
+ ``_
+
+ :param inference_id: The unique identifier for the inference endpoint.
+ :param input: The text on which you want to perform the inference task. It can
+ be a single string or an array. > info > Inference endpoints for the `completion`
+ task type currently only support a single string as input.
+ :param task_type: The type of inference task that the model performs.
+ :param query: The query input, which is required only for the `rerank` task.
+ It is not required for other tasks.
+ :param task_settings: Task settings for the individual inference request. These
+ settings are specific to the task type you specified and override the task
+ settings specified when initializing the service.
+ :param timeout: The amount of time to wait for the inference request to complete.
+ """
+ if inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'inference_id'")
+ if input is None and body is None:
+ raise ValueError("Empty value passed for parameter 'input'")
+ __path_parts: t.Dict[str, str]
+ if task_type not in SKIP_IN_PATH and inference_id not in SKIP_IN_PATH:
+ __path_parts = {
+ "task_type": _quote(task_type),
+ "inference_id": _quote(inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["inference_id"]}'
+ elif inference_id not in SKIP_IN_PATH:
+ __path_parts = {"inference_id": _quote(inference_id)}
+ __path = f'/_inference/{__path_parts["inference_id"]}'
+ else:
+ raise ValueError("Couldn't find a path for the given parameters")
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if timeout is not None:
+ __query["timeout"] = timeout
+ if not __body:
+ if input is not None:
+ __body["input"] = input
+ if query is not None:
+ __body["query"] = query
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return await self.perform_request( # type: ignore[return-value]
+ "POST",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.inference",
+ path_parts=__path_parts,
+ )
+
@_rewrite_parameters(
body_name="chat_completion_request",
)
diff --git a/elasticsearch/_sync/client/inference.py b/elasticsearch/_sync/client/inference.py
index 279528a96..aa2ebde2e 100644
--- a/elasticsearch/_sync/client/inference.py
+++ b/elasticsearch/_sync/client/inference.py
@@ -20,7 +20,13 @@
from elastic_transport import ObjectApiResponse
from ._base import NamespacedClient
-from .utils import SKIP_IN_PATH, _quote, _rewrite_parameters
+from .utils import (
+ SKIP_IN_PATH,
+ Stability,
+ _quote,
+ _rewrite_parameters,
+ _stability_warning,
+)
class InferenceClient(NamespacedClient):
@@ -234,6 +240,117 @@ def get(
path_parts=__path_parts,
)
+ @_rewrite_parameters(
+ body_fields=("input", "query", "task_settings"),
+ )
+ @_stability_warning(
+ Stability.DEPRECATED,
+ version="8.18.0",
+ message="inference.inference() is deprecated in favor of provider-specific APIs such as inference.put_elasticsearch() or inference.put_hugging_face()",
+ )
+ def inference(
+ self,
+ *,
+ inference_id: str,
+ input: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ task_type: t.Optional[
+ t.Union[
+ str,
+ t.Literal[
+ "chat_completion",
+ "completion",
+ "rerank",
+ "sparse_embedding",
+ "text_embedding",
+ ],
+ ]
+ ] = None,
+ error_trace: t.Optional[bool] = None,
+ filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
+ human: t.Optional[bool] = None,
+ pretty: t.Optional[bool] = None,
+ query: t.Optional[str] = None,
+ task_settings: t.Optional[t.Any] = None,
+ timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
+ body: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> ObjectApiResponse[t.Any]:
+ """
+ .. raw:: html
+
+
Perform inference on the service.
+
This API enables you to use machine learning models to perform specific tasks on data that you provide as an input.
+ It returns a response with the results of the tasks.
+ The inference endpoint you use can perform one specific task that has been defined when the endpoint was created with the create inference API.
+
+
info
+ The inference APIs enable you to use certain services, such as built-in machine learning models (ELSER, E5), models uploaded through Eland, Cohere, OpenAI, Azure, Google AI Studio, Google Vertex AI, Anthropic, Watsonx.ai, or Hugging Face. For built-in models and models uploaded through Eland, the inference APIs offer an alternative way to use and manage trained models. However, if you do not plan to use the inference APIs to use these models or if you want to use non-NLP models, use the machine learning trained model APIs.
+
+
+
+ ``_
+
+ :param inference_id: The unique identifier for the inference endpoint.
+ :param input: The text on which you want to perform the inference task. It can
+ be a single string or an array. > info > Inference endpoints for the `completion`
+ task type currently only support a single string as input.
+ :param task_type: The type of inference task that the model performs.
+ :param query: The query input, which is required only for the `rerank` task.
+ It is not required for other tasks.
+ :param task_settings: Task settings for the individual inference request. These
+ settings are specific to the task type you specified and override the task
+ settings specified when initializing the service.
+ :param timeout: The amount of time to wait for the inference request to complete.
+ """
+ if inference_id in SKIP_IN_PATH:
+ raise ValueError("Empty value passed for parameter 'inference_id'")
+ if input is None and body is None:
+ raise ValueError("Empty value passed for parameter 'input'")
+ __path_parts: t.Dict[str, str]
+ if task_type not in SKIP_IN_PATH and inference_id not in SKIP_IN_PATH:
+ __path_parts = {
+ "task_type": _quote(task_type),
+ "inference_id": _quote(inference_id),
+ }
+ __path = f'/_inference/{__path_parts["task_type"]}/{__path_parts["inference_id"]}'
+ elif inference_id not in SKIP_IN_PATH:
+ __path_parts = {"inference_id": _quote(inference_id)}
+ __path = f'/_inference/{__path_parts["inference_id"]}'
+ else:
+ raise ValueError("Couldn't find a path for the given parameters")
+ __query: t.Dict[str, t.Any] = {}
+ __body: t.Dict[str, t.Any] = body if body is not None else {}
+ if error_trace is not None:
+ __query["error_trace"] = error_trace
+ if filter_path is not None:
+ __query["filter_path"] = filter_path
+ if human is not None:
+ __query["human"] = human
+ if pretty is not None:
+ __query["pretty"] = pretty
+ if timeout is not None:
+ __query["timeout"] = timeout
+ if not __body:
+ if input is not None:
+ __body["input"] = input
+ if query is not None:
+ __body["query"] = query
+ if task_settings is not None:
+ __body["task_settings"] = task_settings
+ if not __body:
+ __body = None # type: ignore[assignment]
+ __headers = {"accept": "application/json"}
+ if __body is not None:
+ __headers["content-type"] = "application/json"
+ return self.perform_request( # type: ignore[return-value]
+ "POST",
+ __path,
+ params=__query,
+ headers=__headers,
+ body=__body,
+ endpoint_id="inference.inference",
+ path_parts=__path_parts,
+ )
+
@_rewrite_parameters(
body_name="chat_completion_request",
)
diff --git a/elasticsearch/_sync/client/utils.py b/elasticsearch/_sync/client/utils.py
index 48ebcb217..0708329ba 100644
--- a/elasticsearch/_sync/client/utils.py
+++ b/elasticsearch/_sync/client/utils.py
@@ -77,6 +77,7 @@ class Stability(Enum):
STABLE = auto()
BETA = auto()
EXPERIMENTAL = auto()
+ DEPRECATED = auto()
_TYPE_HOSTS = Union[
@@ -442,6 +443,12 @@ def wrapped(*args: Any, **kwargs: Any) -> Any:
category=GeneralAvailabilityWarning,
stacklevel=warn_stacklevel(),
)
+ elif stability == Stability.DEPRECATED and message and version:
+ warnings.warn(
+ f"In elasticsearch-py {version}, {message}.",
+ category=DeprecationWarning,
+ stacklevel=warn_stacklevel(),
+ )
return api(*args, **kwargs)
From 901dbc30323f024574460de76fdb8fea03ab16f0 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 2 Apr 2025 20:24:30 +0400
Subject: [PATCH 16/57] Add querying docs (#2843) (#2878)
* Add querying docs
It's not always obvious to go from an API to a function call, and this page
contains the details.
* Apply suggestions from code review
Co-authored-by: Miguel Grinberg
* Address more comments
* Rename to Querying for consistency
* Clarify that examples in guide depend on version
---------
Co-authored-by: Miguel Grinberg
(cherry picked from commit 3fcb7193cd7e46bef6edd4ed85934f505fbe5c89)
Co-authored-by: Quentin Pradet
---
docs/images/python-example.png | Bin 0 -> 109584 bytes
docs/reference/querying.md | 106 +++++++++++++++++++++++++++++++++
docs/reference/toc.yml | 1 +
3 files changed, 107 insertions(+)
create mode 100644 docs/images/python-example.png
create mode 100644 docs/reference/querying.md
diff --git a/docs/images/python-example.png b/docs/images/python-example.png
new file mode 100644
index 0000000000000000000000000000000000000000..3eaee6d0224f549152ed9fc0b7063f67822b462e
GIT binary patch
literal 109584
zcmeEu^tDA4G}M1Iak3Gmd84dGEe&x5QuDEMuyfFeVN+96
zi#VEF2x-W?{C9WcH&Gf(CntL$0KnDNmEDz_9pVTAa0&_v0yww;TwH9(7Hm*=u#>49
z8yHIauR;E292p?g%+bo;$qE9d{xz=YTZprhC=Jc8iT?BX*E)f2R)5X}hW`7tkS_@M
z^#s7l&H?z}x;a@{{FiROp8TuZAMf?A=|p}FCZuNN2DH_cv9be#p~$6)32<|Z{4vcx
zp8UDc-+I3JvnMAH2iNaie|z-zuF?=&h@+;xsToj=^WR;5yY*Y^Ukevfb+iH^W%^5U
zzncH!-oM+60Dg(}H!=U~H~ix+@<$ZI76JT6A;hpB!uk|ZP$WN|FK{lI&Udb=g5wow%~?v^grkHH%dbP^V{DSlVpJ6
zZ^R((w;}f5XTk7r!27SSL16EQis6xbjgoQo-)AA%=n(ve0RGdwrRN^OhVv2nr@j9!
z3#1^{|2HZAdyxMV#QzE6uUqW@G~)j>;{Q{P2o`X^8}a_rv-qP?bGY=&ThG6I!eHm59`SBR@l*d$K7e(i1K+rbpB<
z6Hro`mBP5#*T9@E>I_!=7ruEtJhCZ_oRv
zoUYF7j|Qml}OWB$fFJ~+R;}K<-fggB}0R0Ct)BL
z;`(?aQ*7NwCzcC>#l=`E!_Xv3TmbIqK_VS#y2Q_
zEI#@g6FGmBw7G4I>u&@Se!Ecu$2p+O>5D6Iyu7hrqx{k6Ucl{2_35&K!8L|aWas<#Hit=
z=lP!NNA}E!--LiiZIYC}jbhjv!!BT$#$OsNUS&6Qc;>L8u^a;dy2(DRI1
zyt(&vbtq1UQE28e4U6UC!kxxjsSMrzNIE681{b?r>v0KeynMwJqsL72m#oQ;;==dl
zVG(%Gglt`OmmhdBU1Y*M)lau1+xee4I&GsHlJaQBt+duc7D|yyt;^DPIkl
z&&aF9Ay^NI1Ia4N%V*$}ky>?~QC2#@wH+RgLc{Wm=7fkT476N5dzPLQ6LoPlu)V0n
zC<-Ox^iI0Dm9HaZvFhyH#a6CScij}
zp7V$}biLCU=PtdnvY@xn#eHQcWV*_x*BLTh9#$)Z5@9p;?fH0tW?(Q03-dgv4QR2s
zHNMT7LiL!rR-*=NxKjW2?ck`k131xUw*wSb6H$|Nz2M8TaRh7|WedOdDDPU=9LbRF
z09mL)4Zb@DUa&S>y3}(mE(SIP9m5U93`re){dA!+4E=+0B42j8
zG}Z_e4#_CL@tw(Gh!|id(^JP|E#AR;P8I0Ax6}vH%9jf3pv=U=+mZ9?xfrwJj_$#X
z5Tij!+aX_QXV&r(y!jd6nky6ZXv=GMGJI+9^p_J*h{_(_^iRHv~A7T!id1KaIVLb3$p3yrL0=#OT}B?Aq1
zpq6%j>&o7eLUR*rbD(A+>k|<}i~@Z`+eh3CjV#5{ETuSL+Ia^ly&5FbFC;a!L}cScWWj)S<|`<|LN&io=H#PD4c!kQfQy1P;?i2hy>1r4E~c
zgqG%_{%G7|d}&CtXxLM}+?>$J2(J`8G9Ev%s~sgpMMaIP+wBtHHxEx7TMkcqO1fJL
zT|S7-&%e%bVcTLE3<1vx!G-sm00BbN?xBGQ*p~$zL3!}(MdME@^b64lbjyg7-dcso
zL$BbtLpL9z%$K}~9DX}QFs}>#2_L~4@_k|x#a;JAc&e8hs;pH&i~~=QyNWrr1g0
z+qJ9kUOIPM#e7fB53YW)u{#e7xwc)z-Tl!7e=)q>UBck$CH9y_`;}-j?!mseAWL|d
zmjC>-xs@wnK(*90$LX{tQODf_J+i_`^s4}@Q-)jLHXUOhx%0g_?yunM_Sh1JWoPkj
zsD8ZFP*oUtO*a)@PVi*o8T5nk-9Q3wI^R;)T2F~;&U=|-@q}ZsskYDso9IsQ`Ao^*
z%r**I?7bxRVVg$b5?H741{ar?pyt_5U4@g9In!mZ2?l7}@k}XQ3ZD${GD7U~zUcXm
zW;>bltbjBdE31@6&n4D{Mo|Lq>Jf$g13c`EAR>nNLTR#A$>=y^A0xv_t1mFmm2UMz
zx?8RoS7*Ax_xU6gGC-MZ&hxH>PF>ati=oe`N_cC}h~m8{o-F-zzNh|h8V=XQc(*o!
z1Atj@rhx{kSqIu?UUOx!4uGum`lpWTC8d=5%w6?3zxbcGUhVgyM3=Kt!R5d3_D;>k
zba3WAdO}^1F%^N{T=#fG`IG7kybb2CfT|?Hn7K}}rN#(F7Y@+j5$OUvXGqP8lr&!9
z+0T8zP|Z+B-Qo0#Rpn4{pMhLB1$#iF0*&Ue%*BJH#Ex+SvbbJ+>LlP`{Dx8-JO8Gm
z`HIz2OTZ|05UbiC&syhHs$9e~9eOemdb(93zRU5k0?galFU(qKxo(I3KF75?l~|n1
zyY`>GZ?E0kyF$qC2%HVf2M^0ujw>xJbFUXaRa_QXRat)=?T?4AYGH_ogMyFhTK%~O
zElbFrN`d#lT=%c%_*3B)w_o}%i-RO_&urV+=UEJH9j;}*FGooBB>q
zT7QmH>TA62-FBj9<`z!%z5i7hRLwe*aiX4Rl@q!w$6j`@RRG9uap&vzH(+<>av$Xpdf_vy_B5{GD?fzq5QK`g;u*YSbemKP
zf_|JN+HWorOD#5THa(j5x~
zkwrYs>Ig#N`HOZrGOH;Wh|U}@7H^#!+Dvkvx4EtqA~P(S*ovg@JV9O)#kBnEeXP0h
ziTYI|)dJmpl9B3}sTsn^R5%gKAidr9gY
z;(YcYAt6MPp$hbpMk$@A$}uLyldhB|+2$BSePIECauJj{_+r=cxX2~BTyGWZj}@x=
z`ijr>UAWJ`n?UM_Zy^~6M@4j(x%x{P@)e*eyG^UVmyOZ#Ukke|PHq^8O;?X~jqMVo^06gYS@nTx
zFK4l>8ibRVNuuGgamtx5IVEF`w&zKDRdmFKnc5xay7Rrz&w0e)r|K
zoPwZ~n!~;&a|-XsT4$Z9*kgBQop6^ikiz8>QY3zN)XY2JRp&sh
zB`l5wzB4+(7d^Z%D?c+Z{PMg%-g3G#3pW~t!#KM?9!l}LOjf_X|3t&x2mpFsVg%Ek
z__~q?r-gYu0zI0^OeT(V@L@vp!5=L)sJo^P0oCmsbYX_D7A-l74N6qLPK*UD^{qhY
zXZsyt;XG|$)m6I-nfKt=L(TL}tWyS8hdIWwMN48_(4v6u?@Lr%tX1N-!$TS?I~SrE
zC(=5E#4Bshxg>X!KUxI>HMg)f(ILP
zY^!-{YI-)NoLp{LF5g~3vI=X8CQFKDTnQ%Q*Vh(P)CXmSQ(*(WAq6VYu?ZfsWbL%S
z8~1XypG!+LaqbE)KCXOouqa7nytlP6fHe2l_mTmELn;OA))CBhL-XE8e1lCRgIYY_wwkoG{H?vaET%7M;r&?X<9n$!Nk!GZcal-Z+JYc=9YJ#bR~QEu
z^n3>UG2CUWbGH2&b8RmM23!S(Kg2#iptfl8i7%N{)~}AITTPVRCDyHgd5GG&JS!F*
zsA{frup2<;V6)=fQiw7z*^CWa{MoaN*dr#Zq3eTryx*?QeP3Ikf}EF`caH}7
z`a3=NpT0gb3+awrlK}90Hcc|mKtIaKA-qN_rfnB_JH$Ub>{>QWF~`y7vi1sCp~KGH
zL^n@IMmj$PCf@$cJmFN=y#3zRrc72OHVqH;ZPD7xY$0DMe{A{thVb(PqUPY8q&!A_
zpoGc_GejaRkwOWO-tWE>)jv&c$SsjMsHC}?7_&|rzuR(yH)Nq&X}*PdX@x075(7FD
z-fW!EI(s7H5CF*1I^h{8SI>U@UarX@a&$07H0R-3qTDU2WSt