From a0178b8b4818ac1ab08774fdb81c5ad8bed80b48 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 30 Jan 2024 16:25:56 -0800 Subject: [PATCH] Add Support for Vertex Search and Conversation Chat Engine (#9834) * merge change * add chat_engine * update chat engine to allow creating new agent only * fix asyc, update field updatability * update file name * sync product.yaml changes * sync changes * discard product.yaml change * update filename case * add acc test * fix indentation * fix indentation * format * update API to ga and support location parameter * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * minor changes * updating fields * add name output only field, add custom encoder to hardcode solutionType * update documentation * update doc * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * update industryVertical to enum * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * Update mmv1/templates/terraform/examples/discoveryengine_chat_engine_basic.tf.erb Co-authored-by: Stephen Lewis (Burrows) * Update mmv1/templates/terraform/examples/discoveryengine_chat_engine_basic.tf.erb Co-authored-by: Stephen Lewis (Burrows) * remove agent creation location field, set default industryVertical * update test * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * update test * update example and test * remove empty line in test * Apply suggestions from code review Co-authored-by: Stephen Lewis (Burrows) * add vars for TF examples * Update mmv1/products/discoveryengine/ChatEngine.yaml Co-authored-by: Stephen Lewis (Burrows) * Update mmv1/third_party/terraform/services/discoveryengine/resource_discovery_engine_chat_engine_test.go remove duplicate test Co-authored-by: Stephen Lewis (Burrows) * Update mmv1/third_party/terraform/services/discoveryengine/resource_discovery_engine_chat_engine_test.go Co-authored-by: Stephen Lewis (Burrows) * update test names * format code * remove redundant test * Apply suggestions from code review --------- Co-authored-by: Ray Xu Co-authored-by: Stephen Lewis (Burrows) --- mmv1/products/discoveryengine/ChatEngine.yaml | 173 ++++++++++++++++++ ..._chat_engine_hardcode_solution_type.go.erb | 3 + .../discoveryengine_chat_engine_basic.tf.erb | 36 ++++ ...ource_discovery_engine_chat_engine_test.go | 106 +++++++++++ 4 files changed, 318 insertions(+) create mode 100644 mmv1/products/discoveryengine/ChatEngine.yaml create mode 100644 mmv1/templates/terraform/encoders/discovery_engine_chat_engine_hardcode_solution_type.go.erb create mode 100644 mmv1/templates/terraform/examples/discoveryengine_chat_engine_basic.tf.erb create mode 100644 mmv1/third_party/terraform/services/discoveryengine/resource_discovery_engine_chat_engine_test.go diff --git a/mmv1/products/discoveryengine/ChatEngine.yaml b/mmv1/products/discoveryengine/ChatEngine.yaml new file mode 100644 index 000000000000..a32d0459cdbb --- /dev/null +++ b/mmv1/products/discoveryengine/ChatEngine.yaml @@ -0,0 +1,173 @@ +# Copyright 2023 Google Inc. +# Licensed 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. + +--- !ruby/object:Api::Resource +name: 'ChatEngine' +description: | + Vertex chat and Conversation Engine Chat type +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Vertex AI Conversation': 'https://cloud.google.com/dialogflow/cx/docs/concept/generative' + api: 'https://cloud.google.com/generative-ai-app-builder/docs/reference/rest/v1/projects.locations.collections.engines' + +base_url: 'projects/{{project}}/locations/{{location}}/collections/{{collection_id}}/engines/{{engine_id}}' +self_link: 'projects/{{project}}/locations/{{location}}/collections/{{collection_id}}/engines/{{engine_id}}' +create_url: 'projects/{{project}}/locations/{{location}}/collections/{{collection_id}}/engines?engineId={{engine_id}}' +update_url: 'projects/{{project}}/locations/{{location}}/collections/{{collection_id}}/engines/{{engine_id}}' +delete_url: 'projects/{{project}}/locations/{{location}}/collections/{{collection_id}}/engines/{{engine_id}}' + +update_verb: :PATCH +update_mask: true + +autogen_async: true + +async: !ruby/object:Api::OpAsync + actions: ['create', 'delete'] + operation: !ruby/object:Api::OpAsync::Operation + base_url: '{{op_id}}' + result: !ruby/object:Api::OpAsync::Result + resource_inside_response: true + +import_format: + [ + 'projects/{{project}}/locations/{{location}}/collections/{{collection_id}}/engines/{{engine_id}}', + ] + +custom_code: !ruby/object:Provider::Terraform::CustomCode + encoder: templates/terraform/encoders/discovery_engine_chat_engine_hardcode_solution_type.go.erb + +examples: + - !ruby/object:Provider::Terraform::Examples + name: "discoveryengine_chat_engine_basic" + primary_resource_id: 'primary' + vars: + engine_id: "chat-engine-id" + data_store_id: "data-store" + data_store_2_id: "data-store-2" + +parameters: + - !ruby/object:Api::Type::String + name: 'engineId' + description: | + The ID to use for chat engine. + required: true + immutable: true + url_param_only: true + - !ruby/object:Api::Type::String + name: 'collection_id' + description: | + The collection ID. + required: true + immutable: true + url_param_only: true + - !ruby/object:Api::Type::String + name: 'location' + description: | + Location. + required: true + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::String + name: 'name' + description: | + The unique full resource name of the chat engine. Values are of the format + `projects/{project}/locations/{location}/collections/{collection_id}/engines/{engine_id}`. + This field must be a UTF-8 encoded string with a length limit of 1024 + characters. + output: true + - !ruby/object:Api::Type::Enum + name: 'industryVertical' + description: | + The industry vertical that the chat engine registers. Vertical on Engine has to match vertical of the DataStore linked to the engine. + values: + - :GENERIC + immutable: true + default_value: :GENERIC + - !ruby/object:Api::Type::String + name: 'displayName' + description: | + The display name of the engine. Should be human readable. UTF-8 encoded string with limit of 1024 characters. + required: true + - !ruby/object:Api::Type::Array + name: 'dataStoreIds' + min_size: 1 + description: | + The data stores associated with this engine. Multiple DataStores in the same Collection can be associated here. All listed DataStores must be `SOLUTION_TYPE_CHAT`. Adding or removing data stores will force recreation. + required: true + item_type: Api::Type::String + immutable: true + - !ruby/object:Api::Type::Time + name: 'createTime' + description: | + Timestamp the Engine was created at. + output: true + - !ruby/object:Api::Type::Time + name: 'updateTime' + description: | + Timestamp the Engine was last updated. + output: true + - !ruby/object:Api::Type::NestedObject + name: 'chatEngineConfig' + description: | + Configurations for a chat Engine. + required: true + immutable: true + ignore_read: true + properties: + - !ruby/object:Api::Type::NestedObject + name: 'agentCreationConfig' + description: | + The configuration to generate the Dialogflow agent that is associated to this Engine. + required: true + properties: + - !ruby/object:Api::Type::String + name: 'business' + description: | + Name of the company, organization or other entity that the agent represents. Used for knowledge connector LLM prompt and for knowledge search. + - !ruby/object:Api::Type::String + name: 'defaultLanguageCode' + description: | + The default language of the agent as a language tag. See [Language Support](https://cloud.google.com/dialogflow/docs/reference/language) for a list of the currently supported language codes. + required: true + - !ruby/object:Api::Type::String + name: 'timeZone' + description: | + The time zone of the agent from the [time zone database](https://www.iana.org/time-zones), e.g., America/New_York, Europe/Paris. + required: true + - !ruby/object:Api::Type::String + name: 'location' + description: | + Agent location for Agent creation, currently supported values: global/us/eu, it needs to be the same region as the Chat Engine. + - !ruby/object:Api::Type::NestedObject + name: 'commonConfig' + description: | + Common config spec that specifies the metadata of the engine. + immutable: true + properties: + - !ruby/object:Api::Type::String + name: 'companyName' + description: | + The name of the company, business or entity that is associated with the engine. Setting this may help improve LLM related features. + immutable: true + - !ruby/object:Api::Type::NestedObject + name: 'chatEngineMetadata' + description: | + Additional information of the Chat Engine. + output: true + properties: + - !ruby/object:Api::Type::String + name: 'dialogflowAgent' + description: | + The resource name of a Dialogflow agent, that this Chat Engine refers to. + output: true diff --git a/mmv1/templates/terraform/encoders/discovery_engine_chat_engine_hardcode_solution_type.go.erb b/mmv1/templates/terraform/encoders/discovery_engine_chat_engine_hardcode_solution_type.go.erb new file mode 100644 index 000000000000..f84b27a792d2 --- /dev/null +++ b/mmv1/templates/terraform/encoders/discovery_engine_chat_engine_hardcode_solution_type.go.erb @@ -0,0 +1,3 @@ +//hard code solutionType to "SOLUTION_TYPE_CHAT" for chat engine resource +obj["solutionType"] = "SOLUTION_TYPE_CHAT" +return obj, nil \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/discoveryengine_chat_engine_basic.tf.erb b/mmv1/templates/terraform/examples/discoveryengine_chat_engine_basic.tf.erb new file mode 100644 index 000000000000..c8163407135a --- /dev/null +++ b/mmv1/templates/terraform/examples/discoveryengine_chat_engine_basic.tf.erb @@ -0,0 +1,36 @@ +resource "google_discovery_engine_data_store" "test_data_store" { + location = "global" + data_store_id = "<%= ctx[:vars]['data_store_id'] %>" + display_name = "Structured datastore" + industry_vertical = "GENERIC" + content_config = "NO_CONTENT" + solution_types = ["SOLUTION_TYPE_CHAT"] +} + +resource "google_discovery_engine_data_store" "test_data_store_2" { + location = google_discovery_engine_data_store.test_data_store.location + data_store_id = "<%= ctx[:vars]['data_store_2_id'] %>" + display_name = "Structured datastore 2" + industry_vertical = "GENERIC" + content_config = "NO_CONTENT" + solution_types = ["SOLUTION_TYPE_CHAT"] +} + +resource "google_discovery_engine_chat_engine" "primary" { + engine_id = "<%= ctx[:vars]['engine_id'] %>" + collection_id = "default_collection" + location = google_discovery_engine_data_store.test_data_store.location + display_name = "Chat engine" + industry_vertical = "GENERIC" + data_store_ids = [google_discovery_engine_data_store.test_data_store.data_store_id, google_discovery_engine_data_store.test_data_store_2.data_store_id] + common_config { + company_name = "test-company" + } + chat_engine_config { + agent_creation_config { + business = "test business name" + default_language_code = "en" + time_zone = "America/Los_Angeles" + } + } +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/discoveryengine/resource_discovery_engine_chat_engine_test.go b/mmv1/third_party/terraform/services/discoveryengine/resource_discovery_engine_chat_engine_test.go new file mode 100644 index 000000000000..bed2b5218e08 --- /dev/null +++ b/mmv1/third_party/terraform/services/discoveryengine/resource_discovery_engine_chat_engine_test.go @@ -0,0 +1,106 @@ +package discoveryengine_test + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "testing" +) + +func TestAccDiscoveryEngineChatEngine_discoveryengineChatengine_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccDiscoveryEngineChatEngine_discoveryengineChatengine_basic(context), + }, + { + ResourceName: "google_discovery_engine_chat_engine.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"chat_engine_config"}, + }, + { + Config: testAccDiscoveryEngineChatEngine_discoveryengineChatengine_update(context), + }, + { + ResourceName: "google_discovery_engine_chat_engine.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"chat_engine_config"}, + }, + }, + }) +} + +func testAccDiscoveryEngineChatEngine_discoveryengineChatengine_basic(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_discovery_engine_data_store" "test_data_store" { + location = "eu" + data_store_id = "tf-test-data-store-id%{random_suffix}" + display_name = "tf-test-structured-datastore" + industry_vertical = "GENERIC" + content_config = "NO_CONTENT" + solution_types = ["SOLUTION_TYPE_CHAT"] + } + + resource "google_discovery_engine_chat_engine" "primary" { + engine_id = "tf-test-chat-engine-id%{random_suffix}" + collection_id = "default_collection" + location = google_discovery_engine_data_store.test_data_store.location + display_name = "tf-test-chat-engine-name%{random_suffix}" + industry_vertical = "GENERIC" + data_store_ids = [google_discovery_engine_data_store.test_data_store.data_store_id] + common_config { + company_name = "test-company" + } + chat_engine_config { + agent_creation_config { + business = "test business name" + default_language_code = "en" + time_zone = "America/Los_Angeles" + } + } + } + `, context) +} + +func testAccDiscoveryEngineChatEngine_discoveryengineChatengine_update(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_discovery_engine_data_store" "test_data_store" { + location = "eu" + data_store_id = "tf-test-data-store-id%{random_suffix}" + display_name = "tf-test-structured-datastore" + industry_vertical = "GENERIC" + content_config = "NO_CONTENT" + solution_types = ["SOLUTION_TYPE_CHAT"] + } + + + resource "google_discovery_engine_chat_engine" "primary" { + engine_id = "tf-test-chat-engine-id%{random_suffix}" + collection_id = "default_collection" + location = google_discovery_engine_data_store.test_data_store.location + display_name = "tf-test-chat-engine-name-2%{random_suffix}" + industry_vertical = "GENERIC" + data_store_ids = [google_discovery_engine_data_store.test_data_store.data_store_id] + + common_config { + company_name = "test-company" + } + chat_engine_config { + agent_creation_config { + business = "test business name" + default_language_code = "en" + time_zone = "America/Los_Angeles" + } + } + } + `, context) +}