Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Cycle: module.lex.aws_lexv2models_intent.intents, module.lex.aws_lexv2models_slot.slots #39948

Open
bhochhi opened this issue Oct 30, 2024 · 2 comments
Labels
bug Addresses a defect in current functionality. service/lexv2models Issues and PRs that pertain to the lexv2models service.

Comments

@bhochhi
Copy link

bhochhi commented Oct 30, 2024

Terraform Core Version

v1.9.8

AWS Provider Version

5.73.0

Affected Resource(s)

  • aws_lexv2models_bot
  • aws_lexv2models_intent
  • aws_lexv2models_slot

why after the default slot_priority value in intent is not set when provisioning through terraform? and if explicitly want to set this value, you will encounter circular dependency. When I open the intent in the web console and just try to move the slot, build works as if the value for slot_priority been set.

Expected Behavior

once all these resources are applied successfully. One should be able to build the model without any issue.

Actual Behavior

failed to build the lexv2 model. I were not able to build from aws cli nor using web console.

Relevant Error/Panic Output Snippet

the error output running the command was:

│     "botLocaleStatus": "Failed",
│     "failureReasons": [
│         "Slot ids [Department] in intent ContactUs don't define a slot priority. Update the intent to add a priority to these slots."
│     ],

Terraform Configuration Files

resource "aws_lexv2models_bot" "chatbot" {
  name        = var.lex_bot_name
  description = "Chatbot for ${var.project_name}"
  role_arn    = aws_iam_role.lex_bot_role.arn
  type        = "Bot"

  idle_session_ttl_in_seconds = 300

  data_privacy {
    child_directed = false
  }

  tags = {
    Project     = var.project_name
    Environment = var.environment
  }
}

resource "aws_lexv2models_bot_locale" "bot_locale" {
  bot_id      = aws_lexv2models_bot.chatbot.id
  bot_version = var.lex_bot_version
  locale_id   = "en_US"
  description = "English US locale for ${var.lex_bot_name}"

  n_lu_intent_confidence_threshold = 0.40
  depends_on = [aws_lexv2models_bot.chatbot]

}

resource "aws_lexv2models_intent" "intents" {
  for_each    = local.intents
  name        = each.value.name
  description = each.value.description
  bot_id      = aws_lexv2models_bot.chatbot.id
  bot_version = var.lex_bot_version
  locale_id   = aws_lexv2models_bot_locale.bot_locale.locale_id

  dynamic "sample_utterance" {
    for_each = each.value.sample_utterances
    content {
      utterance = sample_utterance.value
    }
  }




  dynamic "fulfillment_code_hook" {
    for_each = lookup(each.value, "fulfillment_code_hook", null) != null ? [each.value.fulfillment_code_hook] : []
    content {
      enabled = fulfillment_code_hook.value.enabled
      post_fulfillment_status_specification {
        success_response {
          message_group {
            message {
              plain_text_message {
                value = fulfillment_code_hook.value.success_response
              }
            }
          }
        }
        failure_response {
          message_group {
            message {
              plain_text_message {
                value = fulfillment_code_hook.value.failure_response
              }
            }
          }
        }
      }
    }
  }

  dynamic "closing_setting" {
    for_each = lookup(each.value, "closing_responses", null) != null ? [each.value.closing_responses] : []
    content {
      active = true

      closing_response {
        message_group {
          message {
            plain_text_message {
              value = closing_setting.value.main_message
            }
          }
          dynamic "variation" {
            for_each = closing_setting.value.variations
            content {
              plain_text_message {
                value = variation.value
              }
            }
          }
        }
      }
    }
  }

  depends_on = [
    aws_lexv2models_bot.chatbot,
    aws_lexv2models_bot_locale.bot_locale
  ]
}

resource "aws_lexv2models_slot" "slots" {
  for_each = { for slot in local.slots_map : slot.intent_name => slot }

  name         = each.value.name
  description  = each.value.description
  slot_type_id = each.value.slot_type_id
  bot_id       = aws_lexv2models_bot.chatbot.id
  bot_version  = var.lex_bot_version
  locale_id    = aws_lexv2models_bot_locale.bot_locale.locale_id
  intent_id    = split(":",aws_lexv2models_intent.intents[each.key].id)[0]

  value_elicitation_setting {
    default_value_specification {
      default_value_list {
        default_value = "Bank"
      }
    }
    slot_constraint = "Required"
    prompt_specification {
      allow_interrupt            = true
      max_retries                = 1
      message_selection_strategy = "Random"

      message_group {
        message {
          plain_text_message {
            value = each.value.prompt
          }
        }
      }

      prompt_attempts_specification {
        allow_interrupt = true
        map_block_key   = "Initial"

        allowed_input_types {
          allow_audio_input = true
          allow_dtmf_input  = true
        }

        audio_and_dtmf_input_specification {
          start_timeout_ms = 4000

          audio_specification {
            end_timeout_ms = 640
            max_length_ms  = 15000
          }

          dtmf_specification {
            deletion_character = "*"
            end_character      = "#"
            end_timeout_ms     = 5000
            max_length         = 513
          }
        }

        text_input_specification {
          start_timeout_ms = 30000
        }
      }

      prompt_attempts_specification {
        allow_interrupt = true
        map_block_key   = "Retry1"

        allowed_input_types {
          allow_audio_input = true
          allow_dtmf_input  = true
        }

        audio_and_dtmf_input_specification {
          start_timeout_ms = 4000

          audio_specification {
            end_timeout_ms = 640
            max_length_ms  = 15000
          }

          dtmf_specification {
            deletion_character = "*"
            end_character      = "#"
            end_timeout_ms     = 5000
            max_length         = 513
          }
        }

        text_input_specification {
          start_timeout_ms = 30000
        }
      }
    }
  }

  depends_on = [
    aws_lexv2models_intent.intents
  ]

}

Steps to Reproduce

all the resources above get provisioned successfully. Then when you build the model either using aws cli or from web console, you will get following error:

"Slot ids [Department] in intent ContactUs don't define a slot priority. Update the intent to add a priority to these slots.”

To address this issue I try to add the slot_priority in the aws_lexv2models_intent resource as follows:

  dynamic "slot_priority" {
     for_each = {for slot in local.slots_map : slot.name => slot if slot.intent_name == each.key}
     content {
       priority = slot_priority.value.priority
       slot_id  = aws_lexv2models_slot.slots[slot_priority.key].id
     }
   }

Unfortunately that mean circular dependency. slot resource need intent but now to set this slot_priority field you need slotId causing cycle:

│ Error: Cycle: module.lex.aws_lexv2models_intent.intents, module.lex.aws_lexv2models_slot.slots


To address this issue, tried to use null_resource to update intent already created with just this slot_priority field. but it seems that it updates everything in the intent and does not preserve the existing values. basically this feels like hack but that requires to get the intent first then update it back with changes.

locals {
  intent_ids = { for k, v in aws_lexv2models_intent.intents : k => split(":", v.id)[0] }
  slot_ids   = { for k, v in aws_lexv2models_slot.slots : k => split(",", v.id)[0] }
}
resource "null_resource" "update_intent_slot_priority" {
    triggers = {
      always_run = timestamp()
    }
  for_each = { for slot in local.slots_map : slot.intent_name => slot }
  provisioner "local-exec" {
    command = <<EOT
    aws lexv2-models update-intent \
      --bot-id ${aws_lexv2models_bot.chatbot.id} \
      --bot-version ${var.lex_bot_version} \
      --locale-id ${aws_lexv2models_bot_locale.bot_locale.locale_id} \
      --intent-id ${local.intent_ids[each.value.intent_name]} \
      --intent-name ${each.value.intent_name} \
      --slot-priorities "[{\"priority\": ${each.value.priority}, \"slotId\": \"${local.slot_ids[each.value.intent_name]}\"}]"
    EOT
  }
  depends_on = [
    aws_lexv2models_intent.intents,
    aws_lexv2models_slot.slots
  ]
}

Debug Output

No response

Panic Output

No response

Important Factoids

No response

References

No response

Would you like to implement a fix?

None

@bhochhi bhochhi added the bug Addresses a defect in current functionality. label Oct 30, 2024
Copy link

Community Note

Voting for Prioritization

  • Please vote on this issue by adding a 👍 reaction to the original post to help the community and maintainers prioritize this request.
  • Please see our prioritization guide for information on how we prioritize.
  • Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request.

Volunteering to Work on This Issue

  • If you are interested in working on this issue, please leave a comment.
  • If this would be your first contribution, please review the contribution guide.

@github-actions github-actions bot added service/lexv2models Issues and PRs that pertain to the lexv2models service. needs-triage Waiting for first response or review from a maintainer. labels Oct 30, 2024
@justinretzolk justinretzolk removed the needs-triage Waiting for first response or review from a maintainer. label Oct 31, 2024
@justinretzolk
Copy link
Member

While I would expect the cycle error in this case (since the two resources point to each other), it's not immediately apparent to me that there's a way around this, so I'd like to leave this open for someone from the team/community to take a look over.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Addresses a defect in current functionality. service/lexv2models Issues and PRs that pertain to the lexv2models service.
Projects
None yet
Development

No branches or pull requests

2 participants