Skip to content

Commit 86e8013

Browse files
authored
feat: add support to specify the exact elser model to install using input elser_model_type. The default value is now .elser_model_2_linux-x86_64 but was previously hard coded to .elser_model_1. If changing the model, the module will first delete the old model before installing the new one. (#259)
1 parent a1355ed commit 86e8013

File tree

13 files changed

+168
-33
lines changed

13 files changed

+168
-33
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ You need the following permissions to run this module.
9494
| <a name="input_backup_encryption_key_crn"></a> [backup\_encryption\_key\_crn](#input\_backup\_encryption\_key\_crn) | The CRN of a KMS (Key Protect or Hyper Protect Crypto Services) key to use for encrypting the disk that holds deployment backups. Applies only if `kms_encryption_enabled` is true. Limitations exist for regions. For more information, see [Key Protect integration](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) or [Hyper Protect Crypto Services integration](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups). | `string` | `null` | no |
9595
| <a name="input_cbr_rules"></a> [cbr\_rules](#input\_cbr\_rules) | The list of context-based restriction rules to create. | <pre>list(object({<br> description = string<br> account_id = string<br> rule_contexts = list(object({<br> attributes = optional(list(object({<br> name = string<br> value = string<br> }))) }))<br> enforcement_mode = string<br> }))</pre> | `[]` | no |
9696
| <a name="input_elasticsearch_version"></a> [elasticsearch\_version](#input\_elasticsearch\_version) | The version of Databases for Elasticsearch to deploy. Possible values: `8.7`, `8.10`, `8.12`, which requires an Enterprise Platinum pricing plan. If no value is specified, the current preferred version for IBM Cloud Databases is used. | `string` | `null` | no |
97+
| <a name="input_elser_model_type"></a> [elser\_model\_type](#input\_elser\_model\_type) | Trained ELSER model to be used for Elastic's Natural Language Processing. Possible values: `.elser_model_1`, `.elser_model_2` and `.elser_model_2_linux-x86_64`. [Learn more](https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html) | `string` | `".elser_model_2_linux-x86_64"` | no |
9798
| <a name="input_enable_elser_model"></a> [enable\_elser\_model](#input\_enable\_elser\_model) | Set it to true to install and start the Elastic's Natural Language Processing model. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-elser-embeddings-elasticsearch) | `bool` | `false` | no |
9899
| <a name="input_existing_kms_instance_guid"></a> [existing\_kms\_instance\_guid](#input\_existing\_kms\_instance\_guid) | The GUID of a Hyper Protect Crypto Services or Key Protect instance for the CRN specified in `kms_key_crn` and `backup_encryption_key_crn`. Applies only if `kms_encryption_enabled` is true, `skip_iam_authorization_policy` is false, and you specify values for `kms_key_crn` or `backup_encryption_key_crn`. | `string` | `null` | no |
99100
| <a name="input_kms_encryption_enabled"></a> [kms\_encryption\_enabled](#input\_kms\_encryption\_enabled) | Whether to specify the keys used to encrypt data in the database. Specify `true` to identify the encryption keys. If set to `false`, the data is encrypted with randomly generated keys. [Learn more about Key Protect integration](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect). [Learn more about HPCS integration](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs). | `bool` | `false` | no |

ibm_catalog.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,26 @@
244244
},
245245
{
246246
"key": "auto_scaling"
247+
},
248+
{
249+
"key": "enable_elser_model"
250+
},
251+
{
252+
"key": "elser_model_type",
253+
"options": [
254+
{
255+
"displayname": ".elser_model_1",
256+
"value": ".elser_model_1"
257+
},
258+
{
259+
"displayname": ".elser_model_2",
260+
"value": ".elser_model_2"
261+
},
262+
{
263+
"displayname": ".elser_model_2_linux-x86_64",
264+
"value": ".elser_model_2_linux-x86_64"
265+
}
266+
]
247267
}
248268
]
249269
}

main.tf

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,23 +289,31 @@ locals {
289289

290290
resource "null_resource" "put_vectordb_model" {
291291
count = var.enable_elser_model ? 1 : 0
292+
triggers = {
293+
file_changed = md5(var.elser_model_type)
294+
}
292295
provisioner "local-exec" {
293296
command = "${path.module}/scripts/put_vectordb_model.sh"
294297
interpreter = ["/bin/bash", "-c"]
295298
environment = {
296-
ES = local.es_url
299+
ES = local.es_url
300+
ELSER_MODEL_TYPE = var.elser_model_type
297301
}
298302
}
299303
}
300304

301305
resource "null_resource" "start_vectordb_model" {
302306
depends_on = [null_resource.put_vectordb_model]
303307
count = var.enable_elser_model ? 1 : 0
308+
triggers = {
309+
file_changed = md5(var.elser_model_type)
310+
}
304311
provisioner "local-exec" {
305312
command = "${path.module}/scripts/start_vectordb_model.sh"
306313
interpreter = ["/bin/bash", "-c"]
307314
environment = {
308-
ES = local.es_url
315+
ES = local.es_url
316+
ELSER_MODEL_TYPE = var.elser_model_type
309317
}
310318
}
311319
}

modules/fscloud/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ No resources.
3737
| <a name="input_backup_encryption_key_crn"></a> [backup\_encryption\_key\_crn](#input\_backup\_encryption\_key\_crn) | The CRN of a Hyper Protect Crypto Services use for encrypting the disk that holds deployment backups. Only used if var.kms\_encryption\_enabled is set to true. There are limitation per region on the Hyper Protect Crypto Services and region for those services. See https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups | `string` | `null` | no |
3838
| <a name="input_cbr_rules"></a> [cbr\_rules](#input\_cbr\_rules) | (Optional, list) List of CBR rules to create | <pre>list(object({<br> description = string<br> account_id = string<br> rule_contexts = list(object({<br> attributes = optional(list(object({<br> name = string<br> value = string<br> }))) }))<br> enforcement_mode = string<br> }))</pre> | `[]` | no |
3939
| <a name="input_elasticsearch_version"></a> [elasticsearch\_version](#input\_elasticsearch\_version) | Version of the Elasticsearch instance. If no value is passed, the current preferred version of IBM Cloud Databases is used. | `string` | `null` | no |
40+
| <a name="input_elser_model_type"></a> [elser\_model\_type](#input\_elser\_model\_type) | Trained ELSER model to be used for Elastic's Natural Language Processing. Possible values: `.elser_model_1`, `.elser_model_2` and `.elser_model_2_linux-x86_64`. [Learn more](https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html) | `string` | `".elser_model_2_linux-x86_64"` | no |
4041
| <a name="input_enable_elser_model"></a> [enable\_elser\_model](#input\_enable\_elser\_model) | Set it to true to install and start the Elastic's Natural Language Processing model. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-elser-embeddings-elasticsearch) | `bool` | `false` | no |
4142
| <a name="input_existing_kms_instance_guid"></a> [existing\_kms\_instance\_guid](#input\_existing\_kms\_instance\_guid) | The GUID of the Hyper Protect Crypto Services instance. It is only required while creating authorization policy. | `string` | `null` | no |
4243
| <a name="input_kms_key_crn"></a> [kms\_key\_crn](#input\_kms\_key\_crn) | The root key CRN of the Hyper Protect Crypto Services (HPCS) to use for disk encryption. | `string` | n/a | yes |

modules/fscloud/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ module "elasticsearch" {
2525
auto_scaling = var.auto_scaling
2626
service_credential_names = var.service_credential_names
2727
enable_elser_model = var.enable_elser_model
28+
elser_model_type = var.elser_model_type
2829
}

modules/fscloud/variables.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,13 @@ variable "enable_elser_model" {
194194
description = "Set it to true to install and start the Elastic's Natural Language Processing model. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-elser-embeddings-elasticsearch)"
195195
default = false
196196
}
197+
198+
variable "elser_model_type" {
199+
type = string
200+
description = "Trained ELSER model to be used for Elastic's Natural Language Processing. Possible values: `.elser_model_1`, `.elser_model_2` and `.elser_model_2_linux-x86_64`. [Learn more](https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html)"
201+
default = ".elser_model_2_linux-x86_64"
202+
validation {
203+
condition = contains([".elser_model_1", ".elser_model_2", ".elser_model_2_linux-x86_64"], var.elser_model_type)
204+
error_message = "The specified elser_model_type is not a valid selection!"
205+
}
206+
}

scripts/put_vectordb_model.sh

Lines changed: 99 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,109 @@
11
#!/bin/bash
22
set -e
33

4-
#Function to install the vectorDB model
5-
Put_model() {
4+
INSTALL_NEW_MODEL=true
65

6+
# get trained models from elasticsearch
7+
echo "Pulling trained models from elasticsearch."
78
sleep=2
89
for i in $(seq 1 4); do
9-
sleep=$((sleep*2))
10-
11-
sleep $sleep
12-
# learn more https://www.elastic.co/docs/api/doc/elasticsearch-serverless/operation/operation-ml-put-trained-model#operation-ml-put-trained-model-wait_for_completion
13-
response=$(curl -s -w "%{http_code}" -kX PUT "$ES/_ml/trained_models/.elser_model_1?wait_for_completion=true&pretty" -H 'Content-Type: application/json' -d'
14-
{
15-
"input": {
16-
"field_names": ["text_field"]
17-
}
18-
}
19-
')
20-
21-
http_code=$(tail -n1 <<< "$response")
22-
content=$(sed '$ d' <<< "$response")
23-
24-
# Check the HTTP status code
25-
if [ "$http_code" -eq 200 ] || [ "$http_code" -eq 201 ]; then
26-
echo "Request sent successfully."
27-
break
28-
else
29-
echo "Failed to install the vectorDB model. HTTP status code: $http_code"
30-
echo "Reponse: $content"
31-
if [ "$i" -eq 4 ]; then
32-
exit 1
10+
11+
sleep=$((sleep*2))
12+
13+
sleep $sleep
14+
result=$(curl -s -w "%{http_code}" -kX GET "$ES/_ml/trained_models?pretty")
15+
16+
http_code=$(tail -n1 <<< "$result")
17+
content=$(sed '$ d' <<< "$result")
18+
# Check the result
19+
if [ "$http_code" -eq 200 ] || [ "$http_code" -eq 201 ]; then
20+
echo "Trained models successfully pulled from elasticsearch."
21+
break
22+
else
23+
echo "Failed to get the trained models from elasticsearch. HTTP status code: $http_code"
24+
echo "Reponse: $content"
25+
if [ "$i" -eq 4 ]; then
26+
exit 1
27+
fi
3328
fi
34-
fi
3529
done
3630

37-
}
31+
# fetch all model_ids created by customer (api_user) from the result
32+
model_ids=$(echo "$content" | jq ".trained_model_configs[] | select(.model_id and .created_by == \"api_user\") | .model_id")
33+
34+
if [[ -z "$model_ids" ]]; then
35+
echo "User has not installed any trained model yet."
36+
else
37+
echo "User's installed trained models: '$model_ids'."
38+
fi
39+
40+
# loop through result and delete unwanted models
41+
for model_id in $model_ids
42+
do
43+
# need to remove double quotes
44+
model=${model_id//"\""/""}
45+
echo "Check if model '$model' should be deleted from elasticsearch."
46+
if [ "$ELSER_MODEL_TYPE" != "$model" ]; then
47+
# deleting trained model
48+
echo "Deleting trained model '$model' from elasticsearch"
49+
sleep=2
50+
for i in $(seq 1 4); do
51+
sleep=$((sleep*2))
52+
53+
sleep $sleep
54+
result=$(curl -s -w "%{http_code}" -kX DELETE "$ES/_ml/trained_models/$model?pretty")
55+
http_code=$(tail -n1 <<< "$result")
56+
content=$(sed '$ d' <<< "$result")
57+
# Check the result
58+
if [ "$http_code" -eq 200 ] || [ "$http_code" -eq 201 ]; then
59+
echo "Trained model '$model' successfully deleted from elasticsearch."
60+
break
61+
else
62+
echo "Failed to delete the trained model '$model' from elasticsearch. HTTP status code: $http_code"
63+
echo "Reponse: $content"
64+
if [ "$i" -eq 4 ]; then
65+
exit 1
66+
fi
67+
fi
68+
done
69+
else
70+
INSTALL_NEW_MODEL=false
71+
echo "Do not delete model '$model' from elasticsearch."
72+
fi
73+
done
74+
75+
# deploy a new trained model using retry
76+
if [ "$INSTALL_NEW_MODEL" = true ] ; then
77+
sleep=2
78+
echo "Deploying the new trained model '$ELSER_MODEL_TYPE' to elasticsearch ..."
79+
for i in $(seq 1 4); do
80+
sleep=$((sleep*2))
81+
82+
sleep $sleep
83+
# learn more https://www.elastic.co/docs/api/doc/elasticsearch-serverless/operation/operation-ml-put-trained-model#operation-ml-put-trained-model-wait_for_completion
84+
response=$(curl -s -w "%{http_code}" -kX PUT "$ES/_ml/trained_models/$ELSER_MODEL_TYPE?wait_for_completion=true&pretty" -H 'Content-Type: application/json' -d'
85+
{
86+
"input": {
87+
"field_names": ["text_field"]
88+
}
89+
}
90+
')
91+
92+
http_code=$(tail -n1 <<< "$response")
93+
content=$(sed '$ d' <<< "$response")
3894

39-
Put_model
95+
# Check the result
96+
if [ "$http_code" -eq 200 ] || [ "$http_code" -eq 201 ]; then
97+
echo "Trained model '$ELSER_MODEL_TYPE' installed successfully."
98+
break
99+
else
100+
echo "Failed to install the model '$ELSER_MODEL_TYPE'. HTTP status code: $http_code"
101+
echo "Reponse: $content"
102+
if [ "$i" -eq 4 ]; then
103+
exit 1
104+
fi
105+
fi
106+
done
107+
else
108+
echo "Model '$ELSER_MODEL_TYPE' already installed. Do not install it."
109+
fi

scripts/start_vectordb_model.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Start_model() {
77
# It takes few minute for the model to finish installing before we can start trained model deployment, therefore we sleep for 180 seconds (3m).
88
sleep 180
99
# Learn more https://www.elastic.co/guide/en/elasticsearch/reference/current/start-trained-model-deployment.html
10-
response=$(curl -s -w "%{http_code}" -kX POST "$ES/_ml/trained_models/.elser_model_1/deployment/_start?wait_for=started&timeout=3m&deployment_id=for_search&pretty")
10+
response=$(curl -s -w "%{http_code}" -kX POST "$ES/_ml/trained_models/$ELSER_MODEL_TYPE/deployment/_start?wait_for=started&timeout=3m&deployment_id=for_search&pretty")
1111

1212
http_code=$(tail -n1 <<< "$response")
1313
content=$(sed '$ d' <<< "$response")

solutions/standard/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ module "elasticsearch" {
118118
auto_scaling = var.auto_scaling
119119
service_credential_names = var.service_credential_names
120120
enable_elser_model = var.enable_elser_model
121+
elser_model_type = var.elser_model_type
121122
}
122123

123124
# this extra block is needed when passing in an existing ES instance - the database data block

solutions/standard/variables.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,13 @@ variable "enable_elser_model" {
237237
description = "Set it to true to install and start the Elastic's Natural Language Processing model. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-elser-embeddings-elasticsearch)"
238238
default = false
239239
}
240+
241+
variable "elser_model_type" {
242+
type = string
243+
description = "Trained ELSER model to be used for Elastic's Natural Language Processing. Possible values: `.elser_model_1`, `.elser_model_2` and `.elser_model_2_linux-x86_64`. [Learn more](https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html)"
244+
default = ".elser_model_2_linux-x86_64"
245+
validation {
246+
condition = contains([".elser_model_1", ".elser_model_2", ".elser_model_2_linux-x86_64"], var.elser_model_type)
247+
error_message = "The specified elser_model_type is not a valid selection!"
248+
}
249+
}

0 commit comments

Comments
 (0)