This is an earlier version of the OpenSearch documentation. For the latest version, see the current documentation. For information about OpenSearch version maintenance, see Release Schedule and Maintenance Policy.
+You're viewing version {{site.opensearch_major_minor_version}} of the OpenSearch documentation. For the latest version, see the current documentation. For information about OpenSearch version maintenance, see Release Schedule and Maintenance Policy.
{% elsif site.doc_version == "unsupported" %} -This version of the OpenSearch documentation is no longer maintained. For the latest version, see the current documentation. For information about OpenSearch version maintenance, see Release Schedule and Maintenance Policy.
+You're viewing version {{site.opensearch_major_minor_version}} of the OpenSearch documentation. This version is no longer maintained. For the latest version, see the current documentation. For information about OpenSearch version maintenance, see Release Schedule and Maintenance Policy.
{% endif %} {% endif %} {% if site.heading_anchors != false %} diff --git a/_ml-commons-plugin/agents-tools/index.md b/_ml-commons-plugin/agents-tools/index.md index ba88edef2f..009906d4cf 100644 --- a/_ml-commons-plugin/agents-tools/index.md +++ b/_ml-commons-plugin/agents-tools/index.md @@ -18,7 +18,7 @@ An _agent_ is a coordinator that uses a large language model (LLM) to solve a pr - [_Flow agent_](#flow-agents): Runs tools sequentially, in the order specified in its configuration. The workflow of a flow agent is fixed. Useful for retrieval-augmented generation (RAG). - [_Conversational flow agent_](#conversational-flow-agents): Runs tools sequentially, in the order specified in its configuration. The workflow of a conversational flow agent is fixed. Stores conversation history so that users can ask follow-up questions. Useful for creating a chatbot. -- [_Conversational agent_](#conversational-agents): Reasons in order to provide a response based on the available knowledge, including the LLM knowledge base and a set of tools provided to the LLM. Stores conversation history so that users can ask follow-up questions. The workflow of a conversational agent is variable, based on follow-up questions. For specific questions, uses the Chain-of-Thought (CoT) process to select the best tool from the configured tools for providing a response to the question. Useful for creating a chatbot that employs RAG. +- [_Conversational agent_](#conversational-agents): Reasons in order to provide a response based on the available knowledge, including the LLM knowledge base and a set of tools provided to the LLM. The LLM reasons iteratively to decide what action to take until it obtains the final answer or reaches the iteration limit. Stores conversation history so that users can ask follow-up questions. The workflow of a conversational agent is variable, based on follow-up questions. For specific questions, uses the Chain-of-Thought (CoT) process to select the best tool from the configured tools for providing a response to the question. Useful for creating a chatbot that employs RAG. ### Flow agents diff --git a/_ml-commons-plugin/agents-tools/tools/connector-tool.md b/_ml-commons-plugin/agents-tools/tools/connector-tool.md new file mode 100644 index 0000000000..dfe4770932 --- /dev/null +++ b/_ml-commons-plugin/agents-tools/tools/connector-tool.md @@ -0,0 +1,168 @@ +--- +layout: default +title: Connector tool +has_children: false +has_toc: false +nav_order: 20 +parent: Tools +grand_parent: Agents and tools +--- + + +# Connector tool +**Introduced 2.15** +{: .label .label-purple } + + +The `ConnectorTool` uses a [connector]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/connectors/) to call any REST API function. For example, you can use a `ConnectorTool` to call a Lambda function through its REST API interface. + +## Step 1: Register a connector with an execute action + +The `ConnectorTool` can only run an `execute` action within a connector. Before you can create a `ConnectorTool`, you need to configure a connector and provide an `execute` action in the `actions` array. The `execute` action is used to invoke a function at a REST API endpoint. It is similar to the `predict` action, which is used to invoke a machine learning (ML) model. + +For this example, you'll create a connector for a simple AWS Lambda function that accepts two integers and returns their sum. This function is hosted on a dedicated endpoint with a specific URL, which you'll provide in the `url` parameter. For more information, see [Lambda function URLs](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html). + +To create a connector, send the following request: + +```json +POST _plugins/_ml/connectors/_create +{ + "name": "Lambda connector of simple calculator", + "description": "Demo connector of lambda function", + "version": 1, + "protocol": "aws_sigv4", + "parameters": { + "region": "YOUR AWS REGION", + "service_name": "lambda" + }, + "credential": { + "access_key": "YOUR ACCESS KEY", + "secret_key": "YOUR SECRET KEY", + "session_token": "YOUR SESSION TOKEN" + }, + "actions": [ + { + "action_type": "execute", + "method": "POST", + "url": "YOUR LAMBDA FUNCTION URL", + "headers": { + "content-type": "application/json" + }, + "request_body": "{ \"number1\":\"${parameters.number1}\", \"number2\":\"${parameters.number2}\" }" + } + ] +} +``` +{% include copy-curl.html %} + +OpenSearch responds with a connector ID: + +```json +{ + "connector_id": "Zz1XEJABXWrLmr4mewEF" +} +``` + +## Step 2: Register a flow agent that will run the ConnectorTool + +For this example, the Lambda function adds the two input numbers and returns their sum in the `result` field: + +```json +{ + "result": 5 +} +``` + +By default, the `ConnectorTool` expects the response from the Lambda function to contain a field named `response`. However, in this example the Lambda function response doesn't include a `response` field. To retrieve the result from the `result` field instead, you need to provide a `response_filter`, specifying the [JSON path](https://github.com/json-path/JsonPath) to the `result` field (`$.result`). Using the `response_filter`, the `ConnectorTool` will retrieve the result with the specified JSON path and return it in the `response` field. + +To configure the Lambda function workflow, create a flow agent. A flow agent runs a sequence of tools in order and returns the last tool's output. To create a flow agent, send the following register agent request, providing the connector ID from the previous step and a `response_filter`: + +```json +POST /_plugins/_ml/agents/_register +{ + "name": "Demo agent of Lambda connector", + "type": "flow", + "description": "This is a demo agent", + "app_type": "demo", + "tools": [ + { + "type": "ConnectorTool", + "name": "lambda_function", + "parameters": { + "connector_id": "YOUR CONNECTOR ID", + "response_filter": "$.result" + } + } + ] +} +``` +{% include copy-curl.html %} + +For parameter descriptions, see [Register parameters](#register-parameters). + +OpenSearch responds with an agent ID: + +```json +{ + "agent_id": "az1XEJABXWrLmr4miAFj" +} +``` + +## Step 3: Run the agent + +Then, run the agent by sending the following request: + +```json +POST /_plugins/_ml/agents/9X7xWI0Bpc3sThaJdY9i/_execute +{ + "parameters": { + "number1": 2, + "number2": 3 + } +} +``` +{% include copy-curl.html %} + +OpenSearch returns the output of the Lambda function execution. In the output, the field name is `response`, and the `result` field contains the Lambda function result: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "response", + "result": 5 + } + ] + } + ] +} +``` + +## Register parameters + +The following table lists all tool parameters that are available when registering an agent. + +Parameter | Type | Required/Optional | Description +:--- | :--- | :--- | :--- +`connector_id` | String | Required | A connector ID of a connector configured with an `execute` action that invokes an API. +`response_filter` | String | Optional | A [JSON path](https://github.com/json-path/JsonPath) to the response field that contains the result of invoking the API. If a `response_filter` is not specified, then the `ConnectorTool` expects the API response to be in a field named `response`. + +## Execute parameters + +When running the agent, you can define any parameter needed for the API call in the `request_body` of your connector's `execute` action. In this example, the parameters are `number1` and `number2`: + +```json +"actions": [ + { + "action_type": "execute", + "method": "POST", + "url": "YOUR LAMBDA FUNCTION URL", + "headers": { + "content-type": "application/json" + }, + "request_body": "{ \"number1\":\"${parameters.number1}\", \"number2\":\"${parameters.number2}\" }" + } + ] +``` \ No newline at end of file diff --git a/_ml-commons-plugin/agents-tools/tools/index.md b/_ml-commons-plugin/agents-tools/tools/index.md index 8db522006e..fba47b63da 100644 --- a/_ml-commons-plugin/agents-tools/tools/index.md +++ b/_ml-commons-plugin/agents-tools/tools/index.md @@ -33,6 +33,7 @@ Each tool takes a list of parameters specific to that tool. In the preceding exa |:--- |:--- | |[`AgentTool`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/agent-tool/) |Runs any agent. | |[`CatIndexTool`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/cat-index-tool/) |Retrieves index information for the OpenSearch cluster. | +|[`ConnectorTool`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/connector-tool/) | Uses a [connector]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/connectors/) to call any REST API function. | |[`IndexMappingTool`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/index-mapping-tool/) |Retrieves index mapping and setting information for an index. | |[`MLModelTool`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/ml-model-tool/) |Runs machine learning models. | |[`NeuralSparseSearchTool`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/neural-sparse-tool/) | Performs sparse vector retrieval. | diff --git a/_ml-commons-plugin/api/model-apis/register-model.md b/_ml-commons-plugin/api/model-apis/register-model.md index 30cc93be00..61d821419e 100644 --- a/_ml-commons-plugin/api/model-apis/register-model.md +++ b/_ml-commons-plugin/api/model-apis/register-model.md @@ -260,15 +260,24 @@ To register an externally hosted model with guardrails, provide the `guardrails` Field | Data type | Description :--- | :--- | :--- -`type` | String | The guardrail type. Currently, only `local_regex` is supported. -`input_guardrail`| Object | The guardrail for the model input. | -`output_guardrail`| Object | The guardrail for the model output. | -`stop_words`| Object | The list of indexes containing stopwords used for the model input/output validation. If the model prompt/response contains a stopword contained in any of the indexes, the predict request on this model is rejected. | -`index_name`| Object | The name of the index storing the stopwords. | -`source_fields`| Object | The name of the field storing the stopwords. | -`regex`| Object | A regular expression used for input/output validation. If the model prompt/response matches the regular expression, the predict request on this model is rejected. | +`type` | String | The guardrail type. Valid values are [`local_regex`](#example-request-regex-and-stopword-validation) and [`model`](#example-request-guardrail-model-validation). Using `local_regex`, you can specify a regular expression or stop words. Using `model`, you can specify a guardrail model. For more information, see [Guardrails]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/guardrails/). +`input_guardrail`| Object | The guardrail for the model input. +`output_guardrail`| Object | The guardrail for the model output. +`stop_words`| Object | The list of indexes containing stopwords used for model input/output validation. If the model prompt/response contains a stopword contained in any of the indexes, then the predict request on the model is rejected. +`index_name`| Object | The name of the index storing the stopwords. +`source_fields`| Object | The name of the field storing the stopwords. +`regex`| Object | A regular expression used for input/output validation. If the model prompt/response matches the regular expression, then the predict request on the model is rejected. +`model_id`| String | The guardrail model used to validate user input and LLM output. +`response_filter`| String | The dot path of the field containing the guardrail model response. +`response_validation_regex`| String | The regular expression used to validate the guardrail model response. -#### Example request: Externally hosted model with guardrails +## Examples + +The following examples configure an externally hosted model with guardrails. + +#### Example request: Regex and stopword validation + +The following example uses a regular expression and a set of stopwords to validate the LLM response: ```json POST /_plugins/_ml/models/_register @@ -303,7 +312,36 @@ POST /_plugins/_ml/models/_register ``` {% include copy-curl.html %} -For a complete example, see [Guardrails]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/guardrails/). +For a complete example, see [Validating input/output using stopwords and regex]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/guardrails/#validating-inputoutput-using-stopwords-and-regex). + +#### Example request: Guardrail model validation + +The following example uses a guardrail model to validate the LLM response: + +```json +POST /_plugins/_ml/models/_register?deploy=true +{ + "name": "Bedrock Claude V2 model with guardrails model", + "function_name": "remote", + "model_group_id": "ppSmpo8Bi-GZ0tf1i7cD", + "description": "Bedrock Claude V2 model with guardrails model", + "connector_id": "xnJjDZABNFJeYR3IPvTO", + "guardrails": { + "input_guardrail": { + "model_id": "o3JaDZABNFJeYR3I2fRV", + "response_validation_regex": "^\\s*\"[Aa]ccept\"\\s*$" + }, + "output_guardrail": { + "model_id": "o3JaDZABNFJeYR3I2fRV", + "response_validation_regex": "^\\s*\"[Aa]ccept\"\\s*$" + }, + "type": "model" + } +} +``` +{% include copy-curl.html %} + +For a complete example, see [Validating input/output using a guardrail model]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/guardrails/#validating-inputoutput-using-a-guardrail-model). #### Example response diff --git a/_ml-commons-plugin/api/model-apis/update-model.md b/_ml-commons-plugin/api/model-apis/update-model.md index e952f9f2bb..048b5b76e5 100644 --- a/_ml-commons-plugin/api/model-apis/update-model.md +++ b/_ml-commons-plugin/api/model-apis/update-model.md @@ -64,12 +64,13 @@ PUT /_plugins/_ml/models/T_S-cY0BKCJ3ot9qr0aP ``` {% include copy-curl.html %} -#### Example request: Updating the guardrails +#### Example requests: Updating the guardrails ```json PUT /_plugins/_ml/models/MzcIJX8BA7mbufL6DOwl { "guardrails": { + "type": "local_regex", "input_guardrail": { "stop_words": [ { @@ -93,6 +94,24 @@ PUT /_plugins/_ml/models/MzcIJX8BA7mbufL6DOwl ``` {% include copy-curl.html %} +```json +PUT /_plugins/_ml/models/9uGdCJABjaMXYrp14YRj +{ + "guardrails": { + "type": "model", + "input_guardrail": { + "model_id": "V-G1CJABjaMXYrp1QoUC", + "response_validation_regex": "^\\s*[Aa]ccept\\s*$" + }, + "output_guardrail": { + "model_id": "V-G1CJABjaMXYrp1QoUC", + "response_validation_regex": "^\\s*[Aa]ccept\\s*$" + } + } +} +``` +{% include copy-curl.html %} + #### Example response ```json diff --git a/_ml-commons-plugin/cluster-settings.md b/_ml-commons-plugin/cluster-settings.md index c473af81a1..37c7cab9f7 100644 --- a/_ml-commons-plugin/cluster-settings.md +++ b/_ml-commons-plugin/cluster-settings.md @@ -108,7 +108,7 @@ plugins.ml_commons.sync_up_job_interval_in_seconds: 3 - Default value: `3` - Value range: [0, 86,400] -## Predict monitoring requests +## Monitoring predict requests Controls how many predict requests are monitored on one node. If set to `0`, OpenSearch clears all monitoring predict requests in cache and does not monitor for new predict requests. @@ -303,12 +303,12 @@ This setting automatically redeploys deployed or partially deployed models upon ### Setting ``` -plugins.ml_commons.model_auto_redeploy.enable: false +plugins.ml_commons.model_auto_redeploy.enable: true ``` ### Values -- Default value: false +- Default value: true - Valid values: `false`, `true` ## Set retires for auto redeploy diff --git a/_ml-commons-plugin/index.md b/_ml-commons-plugin/index.md index c936f36161..f0355b6be3 100644 --- a/_ml-commons-plugin/index.md +++ b/_ml-commons-plugin/index.md @@ -30,4 +30,8 @@ ML Commons supports various algorithms to help train ML models and make predicti ## ML Commons API -ML Commons provides its own set of REST APIs. For more information, see [ML Commons API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/index/). \ No newline at end of file +ML Commons provides its own set of REST APIs. For more information, see [ML Commons API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/index/). + +## Tutorials + +Using the OpenSearch ML framework, you can build various applications, from implementing conversational search to building your own chatbot. For more information, see [Tutorials]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/index/). \ No newline at end of file diff --git a/_ml-commons-plugin/remote-models/batch-ingestion.md b/_ml-commons-plugin/remote-models/batch-ingestion.md new file mode 100644 index 0000000000..64f434e652 --- /dev/null +++ b/_ml-commons-plugin/remote-models/batch-ingestion.md @@ -0,0 +1,250 @@ +--- +layout: default +title: Batch ingestion +has_children: false +nav_order: 80 +parent: Connecting to externally hosted models +grand_parent: Integrating ML models +--- + +# Using externally hosted ML models for batch ingestion + +**Introduced 2.15** +{: .label .label-purple } + +If you are ingesting multiple documents and generating embeddings by invoking an externally hosted model, you can use batch ingestion to improve performance. + +The [Bulk API]({{site.url}}{{site.baseurl}}/api-reference/document-apis/bulk/) accepts a `batch_size` parameter that specifies to process documents in batches of a specified size. Processors that support batch ingestion will send each batch of documents to an externally hosted model in a single request. + +The [`text_embedding`]({{site.url}}{{site.baseurl}}/ingest-pipelines/processors/text-embedding/) and [`sparse_encoding`]({{site.url}}{{site.baseurl}}/ingest-pipelines/processors/sparse-encoding/) processors currently support batch ingestion. + +## Step 1: Register a model group + +You can register a model in two ways: + +* You can use `model_group_id` to register a model version to an existing model group. +* If you do not use `model_group_id`, then ML Commons creates a model with a new model group. + +To register a model group, send the following request: + +```json +POST /_plugins/_ml/model_groups/_register +{ + "name": "remote_model_group", + "description": "A model group for external models" +} +``` +{% include copy-curl.html %} + +The response contains the model group ID that you'll use to register a model to this model group: + +```json +{ + "model_group_id": "wlcnb4kBJ1eYAeTMHlV6", + "status": "CREATED" +} +``` + +To learn more about model groups, see [Model access control]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control/). + +## Step 2: Create a connector + +You can create a standalone connector that can be reused for multiple models. Alternatively, you can specify a connector when creating a model so that it can be used only for that model. For more information and example connectors, see [Connectors]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/connectors/). + +The Connectors Create API, `/_plugins/_ml/connectors/_create`, creates connectors that facilitate registering and deploying external models in OpenSearch. Using the `endpoint` parameter, you can connect ML Commons to any supported ML tool by using its specific API endpoint. For example, you can connect to a ChatGPT model by using the `api.openai.com` endpoint: + +```json +POST /_plugins/_ml/connectors/_create +{ + "name": "OpenAI Chat Connector", + "description": "The connector to public OpenAI model service for GPT 3.5", + "version": 1, + "protocol": "http", + "parameters": { + "endpoint": "api.openai.com", + "model": "gpt-3.5-turbo", + "input_docs_processed_step_size": 100 + }, + "credential": { + "openAI_key": "..." + }, + "actions": [ + { + "action_type": "predict", + "method": "POST", + "url": "https://${parameters.endpoint}/v1/chat/completions", + "headers": { + "Authorization": "Bearer ${credential.openAI_key}" + }, + "request_body": "{ \"model\": \"${parameters.model}\", \"messages\": ${parameters.messages} }" + } + ] +} +``` +{% include copy-curl.html %} + +The `parameters.input_docs_processed_step_size` parameter is used to set the maximum batch size for documents sent to a remote server. You can set this parameter to the maximum batch size supported by the remote server or to a smaller number for optimal performance. + +The response contains the connector ID for the newly created connector: + +```json +{ + "connector_id": "a1eMb4kBJ1eYAeTMAljY" +} +``` + +## Step 3: Register an externally hosted model + +To register an externally hosted model to the model group created in step 1, provide the model group ID from step 1 and the connector ID from step 2 in the following request. You must specify the `function_name` as `remote`: + +```json +POST /_plugins/_ml/models/_register +{ + "name": "openAI-gpt-3.5-turbo", + "function_name": "remote", + "model_group_id": "wlcnb4kBJ1eYAeTMHlV6", + "description": "test model", + "connector_id": "a1eMb4kBJ1eYAeTMAljY" +} +``` +{% include copy-curl.html %} + +OpenSearch returns the task ID of the register operation: + +```json +{ + "task_id": "cVeMb4kBJ1eYAeTMFFgj", + "status": "CREATED" +} +``` + +To check the status of the operation, provide the task ID to the [Tasks API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/tasks-apis/get-task/): + +```json +GET /_plugins/_ml/tasks/cVeMb4kBJ1eYAeTMFFgj +``` +{% include copy-curl.html %} + +When the operation is complete, the state changes to `COMPLETED`: + +```json +{ + "model_id": "cleMb4kBJ1eYAeTMFFg4", + "task_type": "REGISTER_MODEL", + "function_name": "REMOTE", + "state": "COMPLETED", + "worker_node": [ + "XPcXLV7RQoi5m8NI_jEOVQ" + ], + "create_time": 1689793598499, + "last_update_time": 1689793598530, + "is_async": false +} +``` + +Take note of the returned `model_id` because you’ll need it to deploy the model. + +## Step 4: Deploy the model + +Starting in OpenSearch version 2.13, externally hosted models are deployed automatically when you send a Predict API request for the first time. To disable automatic deployment for an externally hosted model, set `plugins.ml_commons.model_auto_deploy.enable` to `false`: + +```json +PUT _cluster/settings +{ + "persistent": { + "plugins.ml_commons.model_auto_deploy.enable" : "false" + } +} +``` +{% include copy-curl.html %} + +To undeploy the model, use the [Undeploy API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/model-apis/undeploy-model/): + +```json +POST /_plugins/_ml/models/cleMb4kBJ1eYAeTMFFg4/_deploy +``` +{% include copy-curl.html %} + +The response contains the task ID, which you can use to check the status of the deploy operation: + +```json +{ + "task_id": "vVePb4kBJ1eYAeTM7ljG", + "status": "CREATED" +} +``` + +As in the previous step, check the status of the operation by calling the Tasks API: + +```json +GET /_plugins/_ml/tasks/vVePb4kBJ1eYAeTM7ljG +``` +{% include copy-curl.html %} + +When the operation is complete, the state changes to `COMPLETED`: + +```json +{ + "model_id": "cleMb4kBJ1eYAeTMFFg4", + "task_type": "DEPLOY_MODEL", + "function_name": "REMOTE", + "state": "COMPLETED", + "worker_node": [ + "n-72khvBTBi3bnIIR8FTTw" + ], + "create_time": 1689793851077, + "last_update_time": 1689793851101, + "is_async": true +} +``` + +## Step 5: Create an ingest pipeline + +The following example request creates an ingest pipeline with a `text_embedding` processor. The processor converts the text in the `passage_text` field into text embeddings and stores the embeddings in `passage_embedding`: + +```json +PUT /_ingest/pipeline/nlp-ingest-pipeline +{ + "description": "A text embedding pipeline", + "processors": [ + { + "text_embedding": { + "model_id": "cleMb4kBJ1eYAeTMFFg4", + "field_map": { + "passage_text": "passage_embedding" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +## Step 6: Perform bulk indexing + +To ingest documents in bulk, call the Bulk API and provide the `batch_size` and `pipeline` parameters. If you don't provide a `pipeline` parameter, the default ingest pipeline for the index will be used for ingestion: + +```json +POST _bulk?batch_size=5&pipeline=nlp-ingest-pipeline +{ "create": { "_index": "testindex1", "_id": "2" } } +{ "passage_text": "hello world" } +{ "create": { "_index": "testindex1", "_id": "3" } } +{ "passage_text": "big apple" } +{ "create": { "_index": "testindex1", "_id": "4" } } +{ "passage_text": "golden gate bridge" } +{ "create": { "_index": "testindex1", "_id": "5" } } +{ "passage_text": "fine tune" } +{ "create": { "_index": "testindex1", "_id": "6" } } +{ "passage_text": "random test" } +{ "create": { "_index": "testindex1", "_id": "7" } } +{ "passage_text": "sun and moon" } +{ "create": { "_index": "testindex1", "_id": "8" } } +{ "passage_text": "windy" } +{ "create": { "_index": "testindex1", "_id": "9" } } +{ "passage_text": "new york" } +{ "create": { "_index": "testindex1", "_id": "10" } } +{ "passage_text": "fantastic" } + +``` +{% include copy-curl.html %} + diff --git a/_ml-commons-plugin/remote-models/blueprints.md b/_ml-commons-plugin/remote-models/blueprints.md index 0f65aee9da..254a21b068 100644 --- a/_ml-commons-plugin/remote-models/blueprints.md +++ b/_ml-commons-plugin/remote-models/blueprints.md @@ -55,41 +55,45 @@ As an ML developer, you can build connector blueprints for other platforms. Usin ## Configuration parameters -| Field | Data type | Is required | Description | -|:------------------------|:------------|:------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `name` | String | Yes | The name of the connector. | -| `description` | String | Yes | A description of the connector. | -| `version` | Integer | Yes | The version of the connector. | -| `protocol` | String | Yes | The protocol for the connection. For AWS services such as Amazon SageMaker and Amazon Bedrock, use `aws_sigv4`. For all other services, use `http`. | -| `parameters` | JSON object | Yes | The default connector parameters, including `endpoint` and `model`. Any parameters indicated in this field can be overridden by parameters specified in a predict request. | -| `credential` | JSON object | Yes | Defines any credential variables required to connect to your chosen endpoint. ML Commons uses **AES/GCM/NoPadding** symmetric encryption to encrypt your credentials. When the connection to the cluster first starts, OpenSearch creates a random 32-byte encryption key that persists in OpenSearch's system index. Therefore, you do not need to manually set the encryption key. | -| `actions` | JSON array | Yes | Defines what actions can run within the connector. If you're an administrator creating a connection, add the [blueprint]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/blueprints/) for your desired connection. | -| `backend_roles` | JSON array | Yes | A list of OpenSearch backend roles. For more information about setting up backend roles, see [Assigning backend roles to users]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control#assigning-backend-roles-to-users). | -| `access_mode` | String | Yes | Sets the access mode for the model, either `public`, `restricted`, or `private`. Default is `private`. For more information about `access_mode`, see [Model groups]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control#model-groups). | -| `add_all_backend_roles` | Boolean | Yes | When set to `true`, adds all `backend_roles` to the access list, which only a user with admin permissions can adjust. When set to `false`, non-admins can add `backend_roles`. | -| `client_config` | JSON object | No | The client configuration object, which provides settings that control the behavior of the client connections used by the connector. These settings allow you to manage connection limits and timeouts, ensuring efficient and reliable communication. | +| Field | Data type | Is required | Description | +|:---|:---|:---|:---| +| `name` | String | Yes | The name of the connector. | +| `description` | String | Yes | A description of the connector. | +| `version` | Integer | Yes | The version of the connector. | +| `protocol` | String | Yes | The protocol for the connection. For AWS services such as Amazon SageMaker and Amazon Bedrock, use `aws_sigv4`. For all other services, use `http`. | +| `parameters` | JSON object | Yes | The default connector parameters, including `endpoint` and `model`. Any parameters indicated in this field can be overridden by parameters specified in a predict request. | +| `credential` | JSON object | Yes | Defines any credential variables required to connect to your chosen endpoint. ML Commons uses **AES/GCM/NoPadding** symmetric encryption to encrypt your credentials. When the connection to the cluster first starts, OpenSearch creates a random 32-byte encryption key that persists in OpenSearch's system index. Therefore, you do not need to manually set the encryption key. | +| `actions` | JSON array | Yes | Defines what actions can run within the connector. If you're an administrator creating a connection, add the [blueprint]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/blueprints/) for your desired connection. | +| `backend_roles` | JSON array | Yes | A list of OpenSearch backend roles. For more information about setting up backend roles, see [Assigning backend roles to users]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control#assigning-backend-roles-to-users). | +| `access_mode` | String | Yes | Sets the access mode for the model, either `public`, `restricted`, or `private`. Default is `private`. For more information about `access_mode`, see [Model groups]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control#model-groups). | +| `add_all_backend_roles` | Boolean | Yes | When set to `true`, adds all `backend_roles` to the access list, which only a user with admin permissions can adjust. When set to `false`, non-admins can add `backend_roles`. | +| `client_config` | JSON object | No | The client configuration object, which provides settings that control the behavior of the client connections used by the connector. These settings allow you to manage connection limits and timeouts, ensuring efficient and reliable communication. | The `actions` parameter supports the following options. -| Field | Data type | Description | -|:------------------------|:------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `action_type` | String | Required. Sets the ML Commons API operation to use upon connection. As of OpenSearch 2.9, only `predict` is supported. | -| `method` | String | Required. Defines the HTTP method for the API call. Supports `POST` and `GET`. | -| `url` | String | Required. Sets the connection endpoint at which the action occurs. This must match the regex expression for the connection used when [adding trusted endpoints]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/index#adding-trusted-endpoints). | -| `headers` | JSON object | Sets the headers used inside the request or response body. Default is `ContentType: application/json`. If your third-party ML tool requires access control, define the required `credential` parameters in the `headers` parameter. | -| `request_body` | String | Required. Sets the parameters contained in the request body of the action. The parameters must include `\"inputText\`, which specifies how users of the connector should construct the request payload for the `action_type`. | -| `pre_process_function` | String | Optional. A built-in or custom Painless script used to preprocess the input data. OpenSearch provides the following built-in preprocess functions that you can call directly:- `connector.pre_process.cohere.embedding` for [Cohere](https://cohere.com/) embedding models
- `connector.pre_process.openai.embedding` for [OpenAI](https://platform.openai.com/docs/guides/embeddings) embedding models
- `connector.pre_process.default.embedding`, which you can use to preprocess documents in neural search requests so that they are in the format that ML Commons can process with the default preprocessor (OpenSearch 2.11 or later). For more information, see [Built-in functions](#built-in-pre--and-post-processing-functions). | -| `post_process_function` | String | Optional. A built-in or custom Painless script used to post-process the model output data. OpenSearch provides the following built-in post-process functions that you can call directly:
- `connector.pre_process.cohere.embedding` for [Cohere text embedding models](https://docs.cohere.com/reference/embed)
- `connector.pre_process.openai.embedding` for [OpenAI text embedding models](https://platform.openai.com/docs/api-reference/embeddings)
- `connector.post_process.default.embedding`, which you can use to post-process documents in the model response so that they are in the format that neural search expects (OpenSearch 2.11 or later). For more information, see [Built-in functions](#built-in-pre--and-post-processing-functions). | +| Field | Data type | Description | +|:---|:---|:---| +| `action_type` | String | Required. Sets the ML Commons API operation to use upon connection. As of OpenSearch 2.9, only `predict` is supported. | +| `method` | String | Required. Defines the HTTP method for the API call. Supports `POST` and `GET`. | +| `url` | String | Required. Sets the connection endpoint at which the action occurs. This must match the regex expression for the connection used when [adding trusted endpoints]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/index#adding-trusted-endpoints). | +| `headers` | JSON object | Sets the headers used inside the request or response body. Default is `ContentType: application/json`. If your third-party ML tool requires access control, define the required `credential` parameters in the `headers` parameter. | +| `request_body` | String | Required. Sets the parameters contained in the request body of the action. The parameters must include `\"inputText\`, which specifies how users of the connector should construct the request payload for the `action_type`. | +| `pre_process_function` | String | Optional. A built-in or custom Painless script used to preprocess the input data. OpenSearch provides the following built-in preprocess functions that you can call directly:
- `connector.pre_process.cohere.embedding` for [Cohere](https://cohere.com/) embedding models
- `connector.pre_process.openai.embedding` for [OpenAI](https://platform.openai.com/docs/guides/embeddings) embedding models
- `connector.pre_process.default.embedding`, which you can use to preprocess documents in neural search requests so that they are in the format that ML Commons can process with the default preprocessor (OpenSearch 2.11 or later). For more information, see [Built-in functions](#built-in-pre--and-post-processing-functions). | +| `post_process_function` | String | Optional. A built-in or custom Painless script used to post-process the model output data. OpenSearch provides the following built-in post-process functions that you can call directly:
- `connector.pre_process.cohere.embedding` for [Cohere text embedding models](https://docs.cohere.com/reference/embed)
- `connector.pre_process.openai.embedding` for [OpenAI text embedding models](https://platform.openai.com/docs/api-reference/embeddings)
- `connector.post_process.default.embedding`, which you can use to post-process documents in the model response so that they are in the format that neural search expects (OpenSearch 2.11 or later). For more information, see [Built-in functions](#built-in-pre--and-post-processing-functions). | The `client_config` parameter supports the following options. -| Field | Data type | Description | -|:---------------------|:----------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `max_connection` | Integer | The maximum number of concurrent connections that the client can establish with the server. | -| `connection_timeout` | Integer | The maximum amount of time (in seconds) that the client will wait while trying to establish a connection to the server. A timeout prevents the client from waiting indefinitely and allows it to recover from unreachable network endpoints. | -| `read_timeout` | Integer | The maximum amount of time (in seconds) that the client will wait for a response from the server after sending a request. Useful when the server is slow to respond or encounters issues while processing a request. | +| Field | Data type | Description | +|:---|:---|:---| +| `max_connection` | Integer | The maximum number of concurrent connections that the client can establish to the server. Some remote services, like SageMaker, constrain the maximum number of concurrent connections and throw a throttling exception if the number of concurrent connections exceeds the threshold. The maximum number of concurrent OpenSearch connections is `max_connection`*`node_number_for_connector`. To mitigate this issue, try to decrease the value of this parameter and modify the retry settings in `client_config`. Default is `30`. | +| `connection_timeout` | Integer | The maximum amount of time (in seconds) that the client will wait while trying to establish a connection to the server. A timeout prevents the client from waiting indefinitely and allows the client to recover when it encounters unreachable network endpoints. | +| `read_timeout` | Integer | The maximum amount of time (in seconds) that the client will wait for a response from the server after sending a request. This is useful when the server is slow to respond or encounters an issue while processing a request. | +| `retry_backoff_policy` | String | The backoff policy for retries to the remote connector. This is useful when there is spike in traffic causing throttling exceptions. Supported policies are `constant`, `exponential_equal_jitter`, and `exponential_full_jitter`. Default is `constant`. | +| `max_retry_times` | Integer | The maximum number of times that a single remote inference request will be retried. This is useful when there is a spike in traffic causing throttling exceptions. When set to `0`, retrying is disabled. When set to `-1`, OpenSearch does not limit the number of `retry_times`. Setting this to a positive integer specifies the maximum number of retry attempts. Default is `0`. | +| `retry_backoff_millis` | Integer | The base backoff time in milliseconds for retry policy. The suspend time during two retries is determined by this parameter and `retry_backoff_policy`. Default is `200`. | +| `retry_timeout_seconds` | Integer | The timeout value, in seconds, for the retry. If the retry can not succeed within the specified amount of time, the connector will stop retrying and throw an exception. Default is `30`. | ## Built-in pre- and post-processing functions diff --git a/_ml-commons-plugin/remote-models/guardrails.md b/_ml-commons-plugin/remote-models/guardrails.md index ca34eb335c..5330454c8b 100644 --- a/_ml-commons-plugin/remote-models/guardrails.md +++ b/_ml-commons-plugin/remote-models/guardrails.md @@ -1,7 +1,7 @@ --- layout: default title: Guardrails -has_children: false +has_children: true has_toc: false nav_order: 70 parent: Connecting to externally hosted models @@ -14,13 +14,21 @@ grand_parent: Integrating ML models Guardrails can guide a large language model (LLM) toward desired behavior. They act as a filter, preventing the LLM from generating output that is harmful or violates ethical principles and facilitating safer use of AI. Guardrails also cause the LLM to produce more focused and relevant output. -To configure guardrails for your LLM, you can provide a list of words to be prohibited in the input or output of the model. Alternatively, you can provide a regular expression against which the model input or output will be matched. +You can configure guardrails for your LLM using the following methods: +- Provide a list of words to be prohibited in the input or output of the model. Alternatively, you can provide a regular expression against which the model input or output will be matched. For more information, see [Validating input/output using stopwords and regex](#validating-inputoutput-using-stopwords-and-regex). +- Configure a separate LLM whose purpose is to validate the user input and the LLM output. ## Prerequisites Before you start, make sure you have fulfilled the [prerequisites]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/index/#prerequisites) for connecting to an externally hosted model. -## Step 1: Create a guardrail index +## Validating input/output using stopwords and regex +**Introduced 2.13** +{: .label .label-purple } + +A simple way to validate the user input and LLM output is to provide a set of prohibited words (stopwords) or a regular expression for validation. + +### Step 1: Create a guardrail index To start, create an index that will store the excluded words (_stopwords_). In the index settings, specify a `title` field, which will contain excluded words, and a `query` field of the [percolator]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/percolator/) type. The percolator query will be used to match the LLM input or output: @@ -41,7 +49,7 @@ PUT /words0 ``` {% include copy-curl.html %} -## Step 2: Index excluded words or phrases +### Step 2: Index excluded words or phrases Next, index a query string query that will be used to match excluded words in the model input or output: @@ -71,7 +79,7 @@ PUT /words0/_doc/2?refresh For more query string options, see [Query string query]({{site.url}}{{site.baseurl}}/query-dsl/full-text/query-string/). -## Step 3: Register a model group +### Step 3: Register a model group To register a model group, send the following request: @@ -95,7 +103,7 @@ The response contains the model group ID that you'll use to register a model to To learn more about model groups, see [Model access control]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control/). -## Step 4: Create a connector +### Step 4: Create a connector Now you can create a connector for the model. In this example, you'll create a connector to the Anthropic Claude model hosted on Amazon Bedrock: @@ -145,7 +153,7 @@ The response contains the connector ID for the newly created connector: } ``` -## Step 5: Register and deploy the model with guardrails +### Step 5: Register and deploy the model with guardrails To register an externally hosted model, provide the model group ID from step 3 and the connector ID from step 4 in the following request. To configure guardrails, include the `guardrails` object: @@ -227,7 +235,7 @@ When the operation is complete, the state changes to `COMPLETED`: } ``` -## Step 6 (Optional): Test the model +### Step 6 (Optional): Test the model To demonstrate how guardrails are applied, first run the predict operation that does not contain any excluded words: @@ -241,7 +249,7 @@ POST /_plugins/_ml/models/p94dYo4BrXGpZpgPp98E/_predict ``` {% include copy-curl.html %} -The response contains inference results: +The response contains the LLM answer: ```json { @@ -293,6 +301,339 @@ The response contains an error message because guardrails were triggered: Guardrails are also triggered when a prompt matches the supplied regular expression. +## Validating input/output using a guardrail model +**Introduced 2.15** +{: .label .label-purple } + +For more advanced validation, you can configure a guardrail model---a separate LLM whose purpose is to validate the user input and the LLM output. In this example, you'll configure two models: +- Chat model: An Anthropic Claude model hosted on Amazon Bedrock whose purpose is to hold a conversation with a user. +- Guardrail model: An OpenAI model whose purpose is to validate the user input and Anthropic Claude output. + +### Step 1: Create a connector for the guardrail model + +First, create a connector to the OpenAI guardrail model. Note that the OpenAI prompt instructs the model to respond only with the words `accept` or `reject`, depending on whether the input/output is acceptable. Additionally, the request contains the `response_filter` parameter, which specifies the field in which the guardrail model will provide the validation result: + +```json +POST /_plugins/_ml/connectors/_create +{ + "name": "openai", + "description": "openai", + "version": "1", + "protocol": "http", + "parameters": { + "endpoint": "api.openai.com", + "max_tokens": 7, + "temperature": 0, + "model": "gpt-3.5-turbo-instruct", + "prompt": "You are a helpful assistant and an expert judge of content quality. Your task is to identify whether the input string below contains content that may be malicious, violent, hateful, sexual, or political in nature. Your answer should consist of a single word, either reject or accept. If the input belongs to any of these categories, please write reject. Otherwise, write accept. \\n\\nHere is the input: ${parameters.question}. \\n\\nYour answer: ", + "response_filter": "$.choices[0].text" + }, + "credential": { + "openAI_key": "
+ Select to expand example response +
+ {: .text-delta} + #### Example response - ```json { "_id": "vd5k2GsBlQ5JUWWFxhsP", @@ -253,13 +247,14 @@ To learn more about using backend roles to limit access, see [(Advanced) Limit a } } ``` +{% include copy-curl.html %} -If you want to specify a time zone, you can do so by including a [cron expression]({{site.url}}{{site.baseurl}}/monitoring-plugins/alerting/cron/) with a time zone name in the `schedule` section of your request. ++ Select to expand example response +
+ {: .text-delta} + #### Example response ```json { @@ -584,6 +590,12 @@ POST _plugins/_alerting/monitors } } ``` +{% include copy-curl.html %} + ++ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "_id": "Q9aXOmkBC25HCRGmzfw-", @@ -900,20 +919,30 @@ PUT _plugins/_alerting/monitors/+ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "_id": "Q9aXOmkBC25HCRGmzfw-", @@ -972,7 +1001,9 @@ GET _plugins/_alerting/monitors/+ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "_nodes": { @@ -1161,20 +1198,30 @@ GET _plugins/_alerting/+ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "_index": ".opensearch-scheduled-jobs", @@ -1191,14 +1238,17 @@ DELETE _plugins/_alerting/monitors/+ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "took": 17, @@ -1288,7 +1345,9 @@ GET _plugins/_alerting/monitors/_search } } ``` +{% include copy-curl.html %} ++ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "monitor_name": "logs", @@ -1321,12 +1385,15 @@ POST _plugins/_alerting/monitors/+ Select to expand example response +
+ {: .text-delta} +#### Example response ```json { "alerts": [ @@ -1406,25 +1479,34 @@ GET _plugins/_alerting/monitors/alerts "totalAlerts": 1 } ``` +{% include copy-curl.html %} + ++ Select to expand example response +
+ {: .text-delta} + + +#### Example response ```json { "success": [ @@ -1433,13 +1515,17 @@ POST _plugins/_alerting/monitors/+ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "_id": "nO-yFmkB8NzS6aXjJdiI", @@ -1508,16 +1601,17 @@ POST _plugins/_alerting/destinations } } ``` +{% include copy-curl.html %} ++ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "_id": "pe-1FmkB8NzS6aXjqvVY", @@ -1556,22 +1657,30 @@ PUT _plugins/_alerting/destinations/+ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "totalDestinations": 1, @@ -1601,22 +1710,30 @@ GET _plugins/_alerting/destinations/+ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "totalDestinations": 1, @@ -1646,20 +1763,30 @@ GET _plugins/_alerting/destinations ] } ``` +{% include copy-curl.html %} ++ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "_index": ".opendistro-alerting-config", @@ -1677,11 +1804,17 @@ DELETE _plugins/_alerting/destinations/+ Select to expand example response +
+ {: .text-delta} #### Example response ```json @@ -1710,12 +1851,15 @@ POST _plugins/_alerting/destinations/email_accounts } } ``` +{% include copy-curl.html %} + ++ Select to expand example response +
+ {: .text-delta} + #### Example response ```json { @@ -1752,10 +1905,15 @@ PUT _plugins/_alerting/destinations/email_accounts/+ Select to expand example response +
+ {: .text-delta} + #### Example response ```json { @@ -1783,15 +1950,28 @@ GET _plugins/_alerting/destinations/email_accounts/+ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "_index" : ".opendistro-alerting-config", @@ -1809,11 +1989,15 @@ DELETE _plugins/_alerting/destinations/email_accounts/+ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "took" : 8, @@ -1873,13 +2064,17 @@ POST _plugins/_alerting/destinations/email_accounts/_search } } ``` +{% include copy-curl.html %} + ++ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "_id" : "email_group_id", @@ -1909,13 +2111,15 @@ POST _plugins/_alerting/destinations/email_groups } } ``` +{% include copy-curl.html %} + ++ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "_id" : "email_group_id", @@ -1952,10 +2164,15 @@ PUT _plugins/_alerting/destinations/email_groups/+ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "_id" : "email_group_id", @@ -1984,15 +2209,28 @@ GET _plugins/_alerting/destinations/email_groups/+ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "_index" : ".opendistro-alerting-config", @@ -2010,11 +2248,15 @@ DELETE _plugins/_alerting/destinations/email_groups/+ Select to expand example response +
+ {: .text-delta} + +#### Example response ```json { "took" : 7, @@ -2075,4 +2324,203 @@ POST _plugins/_alerting/destinations/email_groups/_search } } ``` ---- +{% include copy-curl.html %} + ++ Select to expand example response +
+ {: .text-delta} + +#### Example response +```json +{ + "_id": "0U6aBJABVWc3FrmWer9s", + "_seq_no": 7, + "_primary_term": 2, + "comment": { + "entity_id": "vCZkA5ABWTh3kzuBEL_9", + "entity_type": "alert", + "content": "sample comment", + "created_time": 1718064151148, + "last_updated_time": null, + "user": "admin" + } +} +``` +{% include copy-curl.html %} + ++ Select to expand example response +
+ {: .text-delta} + +#### Example response +```json +{ + "_id": "0U6aBJABVWc3FrmWer9s", + "_seq_no": 8, + "_primary_term": 3, + "comment": { + "entity_id": "vCZkA5ABWTh3kzuBEL_9", + "entity_type": "alert", + "content": "sample updated comment", + "created_time": 1718064151148, + "last_updated_time": 1718064745485, + "user": "admin" + } +} +``` +{% include copy-curl.html %} + ++ Select to expand example response +
+ {: .text-delta} + +#### Example response +```json +{ + "took": 14, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 2, + "relation": "eq" + }, + "max_score": 1, + "hits": [ + { + "_index": ".opensearch-alerting-comments-history-2024.06.10-1", + "_id": "xE5tBJABVWc3FrmWRL5i", + "_version": 1, + "_seq_no": 3, + "_primary_term": 2, + "_score": 1, + "_source": { + "entity_id": "vCZkA5ABWTh3kzuBEL_9", + "entity_type": "alert", + "content": "a different sample comment", + "created_time": 1718061188191, + "last_updated_time": null, + "user": "admin" + } + }, + { + "_index": ".opensearch-alerting-comments-history-2024.06.10-1", + "_id": "0U6aBJABVWc3FrmWer9s", + "_version": 3, + "_seq_no": 9, + "_primary_term": 3, + "_score": 1, + "_source": { + "entity_id": "vCZkA5ABWTh3kzuBEL_9", + "entity_type": "alert", + "content": "sample updated comment", + "created_time": 1718064151148, + "last_updated_time": 1718064745485, + "user": "admin" + } + } + ] + } +} +``` +{% include copy-curl.html %} + ++ Select to expand example response +
+ {: .text-delta} + +#### Example response +```json +{ + "_id": "0U6aBJABVWc3FrmWer9s" +} +``` +{% include copy-curl.html %} + +Space type | -Distance function (d) | -OpenSearch score | -
---|---|---|
l1 | -\[ d(\mathbf{x}, \mathbf{y}) = \sum_{i=1}^n |x_i - y_i| \] | -\[ score = {1 \over 1 + d } \] | -
l2 | -\[ d(\mathbf{x}, \mathbf{y}) = \sum_{i=1}^n (x_i - y_i)^2 \] | -\[ score = {1 \over 1 + d } \] | -
\[ d(\mathbf{x}, \mathbf{y}) = max(|x_i - y_i|) \] | -\[ score = {1 \over 1 + d } \] | -|
cosinesimil | -\[ d(\mathbf{x}, \mathbf{y}) = 1 - cos { \theta } = 1 - {\mathbf{x} · \mathbf{y} \over \|\mathbf{x}\| · \|\mathbf{y}\|}\]\[ = 1 - - {\sum_{i=1}^n x_i y_i \over \sqrt{\sum_{i=1}^n x_i^2} · \sqrt{\sum_{i=1}^n y_i^2}}\] - where \(\|\mathbf{x}\|\) and \(\|\mathbf{y}\|\) represent the norms of vectors x and y respectively. | -nmslib and Faiss:\[ score = {1 \over 1 + d } \] Lucene:\[ score = {2 - d \over 2}\] |
-
innerproduct (supported for Lucene in OpenSearch version 2.13 and later) | -\[ d(\mathbf{x}, \mathbf{y}) = - {\mathbf{x} · \mathbf{y}} = - \sum_{i=1}^n x_i y_i \]
- Lucene: - \[ d(\mathbf{x}, \mathbf{y}) = {\mathbf{x} · \mathbf{y}} = \sum_{i=1}^n x_i y_i \] - |
- \[ \text{If} d \ge 0, \] \[score = {1 \over 1 + d }\] \[\text{If} d < 0, score = −d + 1\]
- Lucene: - \[ \text{If} d > 0, score = d + 1 \] \[\text{If} d \le 0\] \[score = {1 \over 1 + (-1 · d) }\] - |
-
-You can use the **Quick select** settings to specify an exact window of time. -* Select either **Last** or **Next** in the first dropdown list to set the window of time behind the current setting or ahead of the current setting. -* Select a number in the second dropdown list to define a value for the range. -* Select a unit of time in the third dropdown list. Available options are seconds, minutes, hours, days, weeks, months, and years. -Select the **Apply** button to apply the range of dates to the graph. Information on the graph changes accordingly. +You can use the **Quick select** settings to specify a date range: +* Select either **Last** or **Next** from the first dropdown menu to set the date range to either behind the current setting or ahead of the current setting. +* Select a number from the second dropdown menu to define a value for the range. +* Select a unit of time from the third dropdown menu. Available options are seconds, minutes, hours, days, weeks, months, and years. +* Select the **Apply** button to apply the time range to the graph. The graph is immediately updated. + +An example window is shown in the following image. -You can use the left and right arrows to move the window of time behind the current range of dates or ahead of the current range of dates. When you use these arrows, the start date and end date appear in the date range field. You can then select each one to set an absolute, relative, or current date and time. For absolute and relative changes, select the **Update** button to apply the changes. +You can use the left and right arrows in the upper-left corner to shift the time range backward or forward, respectively. When you use these arrows, the start date and end date appear in the date range field. You can then select each one to set an absolute, relative, or current date and time. For absolute and relative changes, select the **Update** button to apply the changes. + +An example window is shown in the following image. -As an alternative, you can select an option in the **Commonly used** section (see the preceding image of the calendar dropdown list) to conveniently set a window of time. Options include date ranges such as **Today**, **Yesterday**, **this week**, and **week to date**. +As an alternative, you can select an option in the **Commonly used** section (see the preceding image of the calendar dropdown menu) to conveniently set a date range. Options include **Today**, **Yesterday**, **this week**, and **week to date**. -When one of the commonly used windows of time is selected, you can select the **Show dates** label in the date range field to populate the range of dates. Following that, you can select either the start date or end date to specify by an absolute, relative, or current date and time setting. For absolute and relative changes, select the **Update** button to apply the changes. +When a commonly used date range is selected, you can select the **Show dates** label in the date range field to populate the ranges. You can then select either the start date or end date to specify an absolute, relative, or current date and time setting. For absolute and relative changes, select the **Update** button to apply the changes. -As one more alternative, you can select an option from the **Recently used date ranges** section to go back to a previous setting. +You can also select an option from the **Recently used date ranges** section to revert to a previous setting. --- -## The Alerts list -The Alerts list displays all findings according to the time when the alert was triggered, the alert's trigger name, the detector that triggered the alert, the alert status, and alert severity. -Use the **Alert severity** dropdown list to filter the list of alerts by severity. Use the **Status** dropdown list to filter the list by alert status. +## Alerts list + +The **Alerts list** displays all alerts, with two tabs for different types of alerts: + +- **Findings**: The **Alerts list** displays all findings according to the time when the alert was triggered, the alert's trigger name, the detector that triggered the alert, the alert status, and the alert severity. +- **Correlations**: The **Alerts list** displays all correlations, including the correlation rule and time window, the alert's trigger name, the correlation rule name that triggered the alert, the alert status, and the alert severity. +Use the **Alert severity** dropdown menu to filter the list of alerts by severity. Use the **Status** dropdown menu to filter the list by alert status. diff --git a/_security/access-control/api.md b/_security/access-control/api.md index bea080a078..63717d621a 100644 --- a/_security/access-control/api.md +++ b/_security/access-control/api.md @@ -815,18 +815,24 @@ Creates, updates, or deletes multiple roles in a single call. PATCH _plugins/_security/api/roles [ { - "op": "replace", "path": "/role1/index_permissions/0/fls", "value": ["test1", "test2"] + "op": "replace", "path": "/role1/index_permissions/0/fls", "value": ["myfield*", "~myfield1"] }, { "op": "remove", "path": "/role1/index_permissions/0/dls" }, { - "op": "add", "path": "/role2/cluster_permissions", "value": ["manage_snapshots"] + "op": "add", "path": "/role2/cluster_permissions/-", "value": { + "index_patterns": ["test_index"], + "allowed_actions": ["indices:data/read/scroll/clear"] + } } ] ``` {% include copy-curl.html %} +You can use `-` to insert a new permission to the end of the array of permissions. +{: .note} + #### Example response ```json @@ -1005,6 +1011,98 @@ PATCH _plugins/_security/api/rolesmapping } ``` +--- + +## Allowlist + +### Get allowlist + +Retrieves the current `allowlist` configuration. + +#### Request + +```json +GET _plugins/_security/api/allowlist +``` +{% include copy-curl.html %} + +#### Example response + +```json +{ + "config" : { + "enabled" : true, + "requests" : { + "/_cat/nodes" : [ + "GET" + ], + "/_cat/indices" : [ + "GET" + ], + "/_plugins/_security/whoami" : [ + "GET" + ] + } + } +} +``` + +### Create allowlist + +Creates an `allowlist` configuration. + +#### Request + +```json +PUT _plugins/_security/api/allowlist +{ + "enabled": true, + "requests": { + "/_cat/nodes": ["GET"], + "/_cat/indices": ["GET"], + "/_plugins/_security/whoami": ["GET"] + } +} +``` +{% include copy-curl.html %} + +#### Example response + +```json +{ + "status":"OK", + "message":"'config' updated." +} +``` + +### Update allowlist + +Updates an `allowlist` configuration. + +#### Request + +```json +PATCH _plugins/_security/api/allowlist +[ + { + "op": "add", + "path": "/config/requests", + "value": { + "/_cat/nodes": ["POST"] + } + } +] +``` +{% include copy-curl.html %} + +#### Example response + +```json +{ + "status":"OK", + "message":"Resource updated." +} +``` --- diff --git a/_security/access-control/field-masking.md b/_security/access-control/field-masking.md index c672e75d04..188def5a6c 100644 --- a/_security/access-control/field-masking.md +++ b/_security/access-control/field-masking.md @@ -12,7 +12,7 @@ redirect_from: If you don't want to remove fields from a document using [field-level security]({{site.url}}{{site.baseurl}}/security/access-control/field-level-security/), you can mask their values. Currently, field masking is only available for string-based fields and replaces the field's value with a cryptographic hash. -Field masking works alongside field-level security on the same per-role, per-index basis. You can allow certain roles to see sensitive fields in plain text and mask them for others. A search result with a masked field might look like this: +Field masking works alongside field-level security on the same per-role, per-index basis. You can allow certain roles to see sensitive fields in plain text and mask them for others. A search result with a masked field might look like the following: ```json { @@ -28,19 +28,20 @@ Field masking works alongside field-level security on the same per-role, per-ind ``` -## Set the salt +## Set the salt setting -You set the salt (a random string used to hash your data) in `opensearch.yml`: +You can set the salt (a random string used to hash your data) in `opensearch.yml` using the optional `plugins.security.compliance.salt` setting. The salt value must fullfil the following requirements: + +- Must be at least 32 characters. +- Use only ASCII characters. + +The following example shows a salt value: ```yml plugins.security.compliance.salt: abcdefghijklmnopqrstuvqxyz1234567890 ``` -Property | Description -:--- | :--- -`plugins.security.compliance.salt` | The salt to use when generating the hash value. Must be at least 32 characters. Only ASCII characters are allowed. Optional. - -Setting the salt is optional, but we highly recommend it. +Although setting the salt is optional, it is highly recommended. ## Configure field masking @@ -78,7 +79,14 @@ See [Create role]({{site.url}}{{site.baseurl}}/security/access-control/api/#crea By default, the Security plugin uses the BLAKE2b algorithm, but you can use any hashing algorithm that your JVM provides. This list typically includes MD5, SHA-1, SHA-384, and SHA-512. -To specify a different algorithm, add it after the masked field: +You can override the default algorithm in `opensearch.yml` using the option default masking algorithm setting `plugins.security.masked_fields.algorithm.default`, as shown in the following example: + +```yml +plugins.security.masked_fields.algorithm.default: SHA-256 +``` +. + +To specify a different algorithm, add it after the masked field in `roles.yml`, as shown in the following: ```yml someonerole: @@ -95,7 +103,7 @@ someonerole: ## (Advanced) Pattern-based field masking -Rather than creating a hash, you can use one or more regular expressions and replacement strings to mask a field. The syntax is `