From ac11f571b45561fe059ec9330214f55c24e23ff2 Mon Sep 17 00:00:00 2001 From: Vipul Date: Thu, 4 Sep 2025 10:06:23 -0700 Subject: [PATCH 1/6] add stack for ai-translation and ai-doc-converter --- .../policies/terraform/api_gateway.tf | 128 ++++++++ .../policies/terraform/container_instances.tf | 36 +++ .../policies/terraform/datasources.tf | 25 ++ .../policies/terraform/identity_app.tf | 20 ++ .../policies/terraform/model_deployment.tf | 61 ++++ .../policies/terraform/network.tf | 199 ++++++++++++ .../policies/terraform/output.tf | 4 + .../policies/terraform/provider.tf | 8 + .../policies/terraform/random.tf | 4 + .../policies/terraform/schema.yaml | 285 ++++++++++++++++++ .../policies/terraform/timeout.tf | 4 + .../policies/terraform/variables.tf | 173 +++++++++++ .../policies/terraform/vault.tf | 37 +++ .../policies/terraform/api_gateway.tf | 127 ++++++++ .../policies/terraform/container_instances.tf | 44 +++ .../policies/terraform/datascience_job.tf | 49 +++ .../policies/terraform/datasources.tf | 25 ++ .../policies/terraform/identity_app.tf | 20 ++ .../policies/terraform/model_deployment.tf | 68 +++++ .../policies/terraform/network.tf | 210 +++++++++++++ .../policies/terraform/output.tf | 4 + .../policies/terraform/provider.tf | 8 + .../policies/terraform/random.tf | 4 + .../policies/terraform/schema.yaml | 221 ++++++++++++++ .../policies/terraform/timeout.tf | 4 + .../policies/terraform/variables.tf | 175 +++++++++++ .../policies/terraform/vault.tf | 37 +++ 27 files changed, 1980 insertions(+) create mode 100644 ai-hub/ai-document-converter/policies/terraform/api_gateway.tf create mode 100644 ai-hub/ai-document-converter/policies/terraform/container_instances.tf create mode 100644 ai-hub/ai-document-converter/policies/terraform/datasources.tf create mode 100644 ai-hub/ai-document-converter/policies/terraform/identity_app.tf create mode 100644 ai-hub/ai-document-converter/policies/terraform/model_deployment.tf create mode 100644 ai-hub/ai-document-converter/policies/terraform/network.tf create mode 100644 ai-hub/ai-document-converter/policies/terraform/output.tf create mode 100644 ai-hub/ai-document-converter/policies/terraform/provider.tf create mode 100644 ai-hub/ai-document-converter/policies/terraform/random.tf create mode 100644 ai-hub/ai-document-converter/policies/terraform/schema.yaml create mode 100644 ai-hub/ai-document-converter/policies/terraform/timeout.tf create mode 100644 ai-hub/ai-document-converter/policies/terraform/variables.tf create mode 100644 ai-hub/ai-document-converter/policies/terraform/vault.tf create mode 100644 ai-hub/ai-translation/policies/terraform/api_gateway.tf create mode 100644 ai-hub/ai-translation/policies/terraform/container_instances.tf create mode 100644 ai-hub/ai-translation/policies/terraform/datascience_job.tf create mode 100644 ai-hub/ai-translation/policies/terraform/datasources.tf create mode 100644 ai-hub/ai-translation/policies/terraform/identity_app.tf create mode 100644 ai-hub/ai-translation/policies/terraform/model_deployment.tf create mode 100644 ai-hub/ai-translation/policies/terraform/network.tf create mode 100644 ai-hub/ai-translation/policies/terraform/output.tf create mode 100644 ai-hub/ai-translation/policies/terraform/provider.tf create mode 100644 ai-hub/ai-translation/policies/terraform/random.tf create mode 100644 ai-hub/ai-translation/policies/terraform/schema.yaml create mode 100644 ai-hub/ai-translation/policies/terraform/timeout.tf create mode 100644 ai-hub/ai-translation/policies/terraform/variables.tf create mode 100644 ai-hub/ai-translation/policies/terraform/vault.tf diff --git a/ai-hub/ai-document-converter/policies/terraform/api_gateway.tf b/ai-hub/ai-document-converter/policies/terraform/api_gateway.tf new file mode 100644 index 00000000..846b30bd --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/api_gateway.tf @@ -0,0 +1,128 @@ +# API Gateway +resource "oci_apigateway_gateway" "ai_application_oci_apigateway_gateway" { + compartment_id = var.compartment_id + display_name = "ai_application_api_gw_${random_string.randomstring.result}" + endpoint_type = "PUBLIC" + response_cache_details { + type = "NONE" + } + subnet_id = local.api_gw_subnet_id +} + +# API Gateway Deployments +resource "oci_apigateway_deployment" "ai_application_apigateway_deployment" { + compartment_id = var.compartment_id + display_name = "api-deployment${random_string.randomstring.result}" + gateway_id = oci_apigateway_gateway.ai_application_oci_apigateway_gateway.id + path_prefix = "/" + specification { + logging_policies { + execution_log { + log_level = "INFO" + } + } + request_policies { + authentication { + is_anonymous_access_allowed = "true" + token_auth_scheme = "Bearer" + token_header = "token" + type = "TOKEN_AUTHENTICATION" + validation_failure_policy { + client_details { + type = "VALIDATION_BLOCK" + } + logout_path = "/logout" + response_type = "CODE" + scopes = ["openid"] + source_uri_details { + type = "VALIDATION_BLOCK" + } + type = "OAUTH2" + use_cookies_for_intermediate_steps = "true" + use_cookies_for_session = "true" + } + validation_policy { + additional_validation_policy { + issuers = ["https://identity.oraclecloud.com/"] + } + client_details { + client_id = oci_identity_domains_app.ai_application_confidential_app.name + client_secret_id = oci_vault_secret.idcs_app_client_secret.id + client_secret_version_number = "1" + type = "CUSTOM" + } + max_cache_duration_in_hours = "1" + source_uri_details { + type = "DISCOVERY_URI" + uri = "${data.oci_identity_domain.application_identity_domain.url}/.well-known/openid-configuration" + } + type = "REMOTE_DISCOVERY" + } + } + mutual_tls { + is_verified_certificate_required = "false" + } + } + routes { + backend { + type = "OAUTH2_LOGOUT_BACKEND" + } + logging_policies { + } + methods = ["GET"] + path = "/logout" + } + routes { + backend { + status = "200" + type = "STOCK_RESPONSE_BACKEND" + } + logging_policies { + } + methods = ["ANY"] + path = "/token" + response_policies { + header_transformations { + set_headers { + items { + if_exists = "OVERWRITE" + name = "token" + values = ["$${request.auth[id_token]}"] + } + items { + if_exists = "OVERWRITE" + name = "x-csrf-token" + values = ["$${request.auth[apigw_csrf_token]}"] + } + } + } + } + } + routes { + backend { + connect_timeout_in_seconds = "60" + is_ssl_verify_disabled = "false" + read_timeout_in_seconds = "120" + send_timeout_in_seconds = "120" + type = "HTTP_BACKEND" + url = "http://${data.oci_core_vnic.ai_application_container_instance_vnic.private_ip_address}:8080/$${request.path[req]}" + } + logging_policies { + } + methods = ["ANY"] + path = "/{req*}" + response_policies { + header_transformations { + set_headers { + items { + name = "X-CSRF-TOKEN" + values = ["$${request.auth[apigw_csrf_token]}"] + if_exists = "OVERWRITE" + } + } + } + } + } + } +} + diff --git a/ai-hub/ai-document-converter/policies/terraform/container_instances.tf b/ai-hub/ai-document-converter/policies/terraform/container_instances.tf new file mode 100644 index 00000000..1f332b46 --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/container_instances.tf @@ -0,0 +1,36 @@ +resource "oci_container_instances_container_instance" "ai_container_instance" { + #Required + availability_domain = var.availability_domain + compartment_id = var.compartment_id + containers { + #Required + image_url = local.image + + #Optional + environment_variables = { + MULTIMODAL_LLM_PROVIDER = var.multimodal_llm_provider + MULTIMODAL_MODEL_NAME = var.multimodal_model_name + MULTIMODAL_MODEL_ENDPOINT = var.multimodal_model_endpoint + MAX_OUTPUT_TOKEN = var.multimodal_max_output_token + GENAI_COMPARTMENT_OCID = var.genai_compartment_ocid + PROMPT_VERSION = var.prompt_version + BACKEND_MD_URL = oci_datascience_model_deployment.ai_deployment.model_deployment_url + } + } + shape = var.container_shape + shape_config { + #Required + ocpus = var.ocpus + + #Optional + memory_in_gbs = var.memory_in_gbs + } + vnics { + #Required + subnet_id = local.app_subnet_id + # private_ip = var.container_instance_private_ip + } + + #Optional + display_name = var.container_display_name +} diff --git a/ai-hub/ai-document-converter/policies/terraform/datasources.tf b/ai-hub/ai-document-converter/policies/terraform/datasources.tf new file mode 100644 index 00000000..a3282382 --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/datasources.tf @@ -0,0 +1,25 @@ +data "oci_core_services" "all_oci_services" { + filter { + name = "name" + values = ["All .* Services In Oracle Services Network"] + regex = true + } +} + +data "oci_identity_availability_domains" "get_availability_domains" { + compartment_id = var.compartment_ocid +} + +data "oci_identity_domain" "application_identity_domain" { + domain_id = trimspace(var.identity_domain_id) + lifecycle { + precondition { + condition = var.identity_domain_id != null + error_message = "Existing domain id must be provided when using an existing domain." + } + } +} + +data "oci_core_vnic" "ai_application_container_instance_vnic" { + vnic_id = oci_container_instances_container_instance.ai_container_instance.vnics[0].vnic_id +} \ No newline at end of file diff --git a/ai-hub/ai-document-converter/policies/terraform/identity_app.tf b/ai-hub/ai-document-converter/policies/terraform/identity_app.tf new file mode 100644 index 00000000..838af102 --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/identity_app.tf @@ -0,0 +1,20 @@ +resource "oci_identity_domains_app" "ai_application_confidential_app" { + based_on_template { + value = "CustomWebAppTemplateId" + well_known_id = "CustomWebAppTemplateId" + } + client_type = "confidential" + description = "Confidential Application for AI Translation Application" + display_name = "ai__translation_application_confidential_app_${random_string.randomstring.result}" + schemas = ["urn:ietf:params:scim:schemas:oracle:idcs:App"] + allowed_operations = ["introspect"] + idcs_endpoint = data.oci_identity_domain.application_identity_domain.url + active = true + is_oauth_client = true + bypass_consent = true + allowed_grants = ["authorization_code", "client_credentials", "urn:ietf:params:oauth:grant-type:jwt-bearer", "implicit"] + all_url_schemes_allowed = true + redirect_uris = ["https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/html/convert", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/api/docs", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/callback"] + post_logout_redirect_uris = ["https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/"] + audience = oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname +} \ No newline at end of file diff --git a/ai-hub/ai-document-converter/policies/terraform/model_deployment.tf b/ai-hub/ai-document-converter/policies/terraform/model_deployment.tf new file mode 100644 index 00000000..5f943844 --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/model_deployment.tf @@ -0,0 +1,61 @@ +# Model deployment with custom network and scaling policy type = FIXED SIZE +resource "oci_datascience_model_deployment" "ai_deployment" { + # Required + display_name = var.deployment_display_name + description = local.md_desc + compartment_id = var.data_science_project_compartment_id + project_id = var.project_ocid + + model_deployment_configuration_details { + deployment_type = var.deployment_type + model_configuration_details { + # Required + instance_configuration { + instance_shape_name = var.shape + model_deployment_instance_shape_config_details { + memory_in_gbs = var.memory_in_gbs + ocpus = var.ocpus + } + # Required for custom networking + # subnet_id = var.subnet_ocid + subnet_id = local.app_subnet_id + } + model_id = local.model_id + bandwidth_mbps = var.deployment_bandwidth_mbps + scaling_policy { + instance_count = var.deployment_instance_count + policy_type = "FIXED_SIZE" + } + } + + environment_configuration_details { + image = local.image + image_digest = local.digest + environment_configuration_type = "OCIR_CONTAINER" + # Environment variables are customized based on the AI app. + environment_variables = { + # OCI GenAI Service + MULTIMODAL_LLM_PROVIDER = var.multimodal_llm_provider + MULTIMODAL_MODEL_NAME = var.multimodal_model_name + MULTIMODAL_MODEL_ENDPOINT = var.multimodal_model_endpoint + MAX_OUTPUT_TOKEN = var.multimodal_max_output_token + GENAI_COMPARTMENT_OCID = var.genai_compartment_ocid + PROMPT_VERSION = var.prompt_version, + MODEL_DEPLOY_CUSTOM_ENDPOINTS = "[{\"endpointURI\": \"/apis\", \"httpMethods\": [\"GET\"]}, {\"endpointURI\": \"/convert\", \"httpMethods\": [\"POST\"]}, {\"endpointURI\": \"/convert/file\", \"httpMethods\": [\"POST\"]}]" + } + } + } + + # Logging, use the same log group and log ocid to reduce the variables. + category_log_details { + access { + log_group_id = var.log_group_ocid + log_id = var.log_ocid + } + predict { + log_group_id = var.log_group_ocid + log_id = var.log_ocid + } + } + +} \ No newline at end of file diff --git a/ai-hub/ai-document-converter/policies/terraform/network.tf b/ai-hub/ai-document-converter/policies/terraform/network.tf new file mode 100644 index 00000000..f06a322a --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/network.tf @@ -0,0 +1,199 @@ +# VCN +resource "oci_core_vcn" "aih_vcn" { + count = var.create_new_vcn ? 1 : 0 + cidr_block = var.vcn_cidr + compartment_id = var.vcn_compartment_id + display_name = var.vcn_display_name +} + +# Gateways/ Route Table Enties for Public Subnet which will contain Load Balancer +resource "oci_core_internet_gateway" "igw" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.vcn_compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "public-subnet-igw" + enabled = true +} + +resource "oci_core_route_table" "public_subnet_route_table" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.vcn_compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "Public Subnet Route Table" + route_rules { + destination = "0.0.0.0/0" + network_entity_id = oci_core_internet_gateway.igw[0].id + destination_type = "CIDR_BLOCK" + } +} + +# NAT Gateway and Service gateway for private subnet which will conatain the instance serving Ui Application + +resource "oci_core_nat_gateway" "nat_gatway" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.vcn_compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "private-subnet-nat-gtw" +} + +resource "oci_core_service_gateway" "service_gateway" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.vcn_compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "private-subnet-service-gtw" + services { + service_id = lookup(data.oci_core_services.all_oci_services.services[0], "id") + } +} + +resource "oci_core_route_table" "private_subnet_route_table" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.vcn_compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "Private Subnet Route Table" + route_rules { + destination = "0.0.0.0/0" + network_entity_id = oci_core_nat_gateway.nat_gatway[0].id + destination_type = "CIDR_BLOCK" + } + route_rules { + destination = lookup(data.oci_core_services.all_oci_services.services[0], "cidr_block") + destination_type = "SERVICE_CIDR_BLOCK" + network_entity_id = oci_core_service_gateway.service_gateway[0].id + description = "Terraformed - Auto-generated at Service Gateway creation: All Services in region to Service Gateway" + } +} + +#Security List for Public Subnet + +resource "oci_core_security_list" "public_subnet_security_list" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.vcn_compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "PublicSubnetSL" + + # Inbound Rules + ingress_security_rules { + protocol = "6" # TCP + source = "0.0.0.0/0" + source_type = "CIDR_BLOCK" + tcp_options { + min = 80 + max = 80 + } + description = "Allow HTTP traffic" + } + + ingress_security_rules { + // allow all SSH + protocol = "6" + source = "0.0.0.0/0" + + source_type = "CIDR_BLOCK" + tcp_options { + min = 22 + max = 22 + } + } + + ingress_security_rules { + protocol = "6" # TCP + source = "0.0.0.0/0" + source_type = "CIDR_BLOCK" + tcp_options { + min = 443 + max = 443 + } + description = "Allow HTTPS traffic" + } + + # Outbound Rules + egress_security_rules { + protocol = "all" + destination = "0.0.0.0/0" + description = "Allow all outbound traffic" + } +} + +resource "oci_core_security_list" "private_subnet_security_list" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.vcn_compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "PrivateSubnetSL" + egress_security_rules { + destination = "0.0.0.0/0" + protocol = "all" + } + # HTTP Traffic + ingress_security_rules { + protocol = 6 + source = "0.0.0.0/0" + + source_type = "CIDR_BLOCK" + tcp_options { + max = 80 + min = 80 + } + } + # SSH Access + ingress_security_rules { + protocol = 6 + source = "0.0.0.0/0" + + source_type = "CIDR_BLOCK" + tcp_options { + max = 22 + min = 22 + } + } + # Allowing Traffic on port 8080 + ingress_security_rules { + protocol = 6 + source = "0.0.0.0/0" + + source_type = "CIDR_BLOCK" + tcp_options { + max = 8080 + min = 8080 + } + } + # Allowing Traffic on port 8000 + ingress_security_rules { + protocol = 6 + source = "0.0.0.0/0" + + source_type = "CIDR_BLOCK" + tcp_options { + max = 8000 + min = 8000 + } + } +} + +# Create Subnets + +resource "oci_core_subnet" "app_oci_core_subnet" { + count = var.create_new_vcn ? 1 : 0 + display_name = "app-subnet-${formatdate("MMDDhhmm", timestamp())}" + cidr_block = var.app_subnet_cidr + compartment_id = var.vcn_compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + prohibit_internet_ingress = true + prohibit_public_ip_on_vnic = true + security_list_ids = [oci_core_security_list.private_subnet_security_list[0].id] + route_table_id = oci_core_route_table.private_subnet_route_table[0].id +} + +resource "oci_core_subnet" "api_gw_oci_core_subnet" { + count = var.create_new_vcn ? 1 : 0 + cidr_block = var.api_gw_subnet_cidr + compartment_id = var.vcn_compartment_id + display_name = "api-gw-subnet-${formatdate("MMDDhhmm", timestamp())}" + vcn_id = oci_core_vcn.aih_vcn[0].id + prohibit_internet_ingress = false + prohibit_public_ip_on_vnic = false + security_list_ids = [oci_core_security_list.public_subnet_security_list[0].id] + route_table_id = oci_core_route_table.public_subnet_route_table[0].id +} + + diff --git a/ai-hub/ai-document-converter/policies/terraform/output.tf b/ai-hub/ai-document-converter/policies/terraform/output.tf new file mode 100644 index 00000000..d42e2eaa --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/output.tf @@ -0,0 +1,4 @@ +output "app_url" { + description = "Application URL" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}ui/" +} \ No newline at end of file diff --git a/ai-hub/ai-document-converter/policies/terraform/provider.tf b/ai-hub/ai-document-converter/policies/terraform/provider.tf new file mode 100644 index 00000000..76475433 --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/provider.tf @@ -0,0 +1,8 @@ +terraform { + required_version = ">= 1.0" +} + +provider "oci" { + region = var.region + tenancy_ocid = var.tenancy_ocid +} \ No newline at end of file diff --git a/ai-hub/ai-document-converter/policies/terraform/random.tf b/ai-hub/ai-document-converter/policies/terraform/random.tf new file mode 100644 index 00000000..3e16cc0e --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/random.tf @@ -0,0 +1,4 @@ +resource "random_string" "randomstring" { + length = 10 + special = false +} \ No newline at end of file diff --git a/ai-hub/ai-document-converter/policies/terraform/schema.yaml b/ai-hub/ai-document-converter/policies/terraform/schema.yaml new file mode 100644 index 00000000..23b20054 --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/schema.yaml @@ -0,0 +1,285 @@ +title: "AI Solutions - PDF to Markdown Application" +stackDescription: Deploy PDF to Markdown Application with Authentication with OCI IAM via Resource Manager Stack +description: "Deploy PDF to Markdown Application with Authentication with OCI IAM via Resource Manager Stack" +schemaVersion: 1.1.0 +version: "20190404" +locale: "en" + +variableGroups: + - title: Hide constants and internal variables + visible: false + variables: + - tenancy_ocid + - compartment_ocid + - current_user_ocid + - region + - shape + - model_backend + - model_name + - model_url + - openai_api_key + - translation_log_dir + - num_workers + - vcn_display_name + - multimodal_model_name + - deployment_type + - deployment_bandwidth_mbps + - deployment_instance_count + - model_backend + - model_name + - model_url + - oci_cache_endpoint + - openai_api_key + - translation_log_dir + - num_workers + - multimodal_llm_provider + - multimodal_max_output_token + - multimodal_model_endpoint + - prompt_version + - log_group_ocid + - log_ocid + + - title: "General Configuration" + variables: + - compartment_id + - availability_domain + - data_science_project_ocid + - title: "Network" + variables: + - vcn_compartment_id + - create_new_vcn + - existing_vcn_id + - vcn_cidr + - existing_app_subnet_id + - app_subnet_cidr + - existing_api_gw_subnet_id + - api_gw_subnet_cidr + - title: "Authentication Configuration" + variables: + - identity_domain_compartment_id + - identity_domain_id + - vault_compartment_id + - use_existing_vault + - new_vault_display_name + - vault_id + - key_id + - title: "Application Container Instance Configurations" + variables: + - container_display_name + - container_shape + - memory_in_gbs + - ocpus + - title: "Application Configuration" + variables: + - genai_compartment_ocid + - data_science_project_compartment_id + - project_ocid + - deployment_display_name + + +variables: + # General Configuration + compartment_id: + type: oci:identity:compartment:id + required: true + title: Compartment Id + description: Default Compartment Id + default: compartment_ocid + availability_domain: + type: oci:identity:availabilitydomain:name + required: true + title: Availability domain + description: The availability domain in which to create Compute resources. + dependsOn: + compartmentId: ${compartment_id} + #Network Configuration + vcn_compartment_id: + type: oci:identity:compartment:id + required: true + title: VCN Compartment Id + description: Compartment in which VCN, Subnets needs to be created or present. + default: compartment_ocid + create_new_vcn: + type: boolean + required: true + title: Create New VCN, Subnet, NAT Gateway, Internet Gateway, etc. for the application + default: true + existing_vcn_id: + type: oci:core:vcn:id + required: true + title: Select to VCN + visible: + not: + - create_new_vcn + dependsOn: + compartmentId: ${vcn_compartment_id} + vcn_cidr: + type: string + required: true + title: VCN IPv4 CIDR Blocks + description: This VCN will be used for all resources created by the stack. + default: "10.1.0.0/16" + pattern: "^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\/(3[0-2]|[1-2]?[0-9])$" + visible: create_new_vcn + existing_app_subnet_id: + type: oci:core:subnet:id + required: true + title: Select the application subnet + dependsOn: + compartmentId: ${vcn_compartment_id} + vcnId: ${existing_vcn_id} + hidePublicSubnet: true + visible: + not: + - create_new_vcn + app_subnet_cidr: + type: string + required: true + title: Application Subnet IPv4 CIDR Blocks + description: The container instances running the application will be created in this subnet. + default: "10.1.1.0/24" + pattern: "^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\/(3[0-2]|[1-2]?[0-9])$" + visible: create_new_vcn + existing_api_gw_subnet_id: + type: oci:core:subnet:id + required: true + title: Select the API Gateway subnet + dependsOn: + compartmentId: ${vcn_compartment_id} + vcnId: ${existing_vcn_id} + hidePublicSubnet: false + visible: + not: + - create_new_vcn + api_gw_subnet_cidr: + type: string + required: true + title: API Gateway Subnet IPv4 CIDR Blocks + description: API Gateway will be created in this subnet. + pattern: "^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\/(3[0-2]|[1-2]?[0-9])$" + default: "10.1.2.0/24" + visible: create_new_vcn + #Application Configuration + identity_domain_compartment_id: + type: oci:identity:compartment:id + required: true + title: Identity Domain Compartment Id + description: Compartment in which Identity Domain is present. + default: compartment_ocid + identity_domain_id: + type: oci:identity:domains:id + required: true + title: Identity domain + description: Identity Domain in which confidential integrated application needs to be created + visible: true + dependsOn: + compartmentId: ${identity_domain_compartment_id} + # Vault Configuration + vault_compartment_id: + type: oci:identity:compartment:id + required: true + title: Vault Compartment Id + description: Compartment in which Vault is present. + default: compartment_ocid + use_existing_vault: + type: boolean + title: Use an existing key vault + required: true + default: true + description: This vault will be used to store client secret of identity application used by API Gateway for Authentication. + new_vault_display_name: + type: string + title: Key vault display name + description: A user-friendly name to help you easily identify the resource. + required: true + visible: + not: + - use_existing_vault + vault_id: + type: oci:kms:vault:id + required: true + title: Vault + description: Choose an existing vault used to store the client secret. + dependsOn: + compartmentId: ${vault_compartment_id} + visible: + and: + - use_existing_vault + key_id: + type: oci:kms:key:id + required: true + title: Encryption key + description: This key will be used to encrypt the sensitive information stored as vault secrets. + dependsOn: + compartmentId: ${vault_compartment_id} + vaultId: ${vault_id} + visible: + and: + - use_existing_vault + # Container instances configuration + container_display_name: + type: string + title: Container Instance display name + description: A user-friendly name to help you easily identify the container instance resource. + required: true + container_shape: + type: enum + required: true + title: Container instance shape + description: A shape is a template that determines the number of OCPUs, amount of memory, and other resources that are allocated to a container instance. + default: "CI.Standard.E4.Flex" + enum: + - CI.Standard.E3.Flex + - CI.Standard.E4.Flex + memory_in_gbs: + type: number + required: true + title: Memory (GB) + default: 16 + minimum: 1 + maximum: 1024 + description: Min - 1 GB or a value matching the number of OCPUs, whichever is greater. Max - 64 GB per OCPU, up to 1024 GB total + ocpus: + type: number + required: true + title: OCPU + description: Min - 1 OCPU. Max - 64 OCPU + default: 1 + minimum: 1 + maximum: 64 + # Application Configuration" + data_science_project_compartment_id: + type: oci:identity:compartment:id + required: true + title: Data Science Project Compartment Id + description: Compartment in which Data Science Project is present. + default: compartment_ocid + project_ocid: + type: oci:ods:project:id + required: true + title: Select Data Science Project + dependsOn: + compartmentId: ${data_science_project_compartment_id} + genai_compartment_ocid: + type: oci:identity:compartment:id + required: true + title: Gen AI Compartment OCID + deployment_display_name: + type: string + title: Model Deployment display name + description: A user-friendly name to help you easily identify the Model Deployment resource in Data Science Project. + required: true + + +outputGroups: + - title: "Application URL" + outputs: + - app_url + +outputs: + app_url: + type: link + title: "Playground UI URL" + visible: true + + diff --git a/ai-hub/ai-document-converter/policies/terraform/timeout.tf b/ai-hub/ai-document-converter/policies/terraform/timeout.tf new file mode 100644 index 00000000..5516967b --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/timeout.tf @@ -0,0 +1,4 @@ +// Timeout to make sure the network is complete before start creating the containers +resource "time_sleep" "wait_seconds" { + create_duration = "150s" +} \ No newline at end of file diff --git a/ai-hub/ai-document-converter/policies/terraform/variables.tf b/ai-hub/ai-document-converter/policies/terraform/variables.tf new file mode 100644 index 00000000..a9aef70a --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/variables.tf @@ -0,0 +1,173 @@ +variable "tenancy_ocid" {} +variable "compartment_ocid" {} +variable "region" {} + +variable "compartment_id" { + description = "The selected compartment, by default the compartment in which stack is created" + type = string +} + +variable "availability_domain" { + description = "Availabiliy domain" + type = string +} +# Network configuration CIDR + +variable "create_new_vcn" { + type = bool + default = true +} +variable "vcn_compartment_id" { + description = "Compartment in which VCN, Subnets needs to be created or present" + type = string +} +variable "existing_vcn_id" { + type = string + default = "" +} +variable "vcn_display_name" { + default = "ai-solutions-vcn" +} +variable "vcn_cidr" { + type = string + default = "10.1.0.0/16" +} +variable "existing_app_subnet_id" { + type = string + default = "" +} +variable "app_subnet_cidr" { + type = string + default = "10.1.2.0/24" +} +variable "existing_api_gw_subnet_id" { + type = string + default = "" +} +variable "api_gw_subnet_cidr" { + type = string + default = "10.1.1.0/24" +} + +#IDCS Configuration +variable "identity_domain_compartment_id" { + description = "Compartment in which identity domain is present" + type = string +} +variable "identity_domain_id" { + type = string + default = "" +} + +#Vault Configuration to Store Identity App Client Secret +variable "vault_compartment_id" { + description = "Compartment in which Vault is present" + type = string +} +variable "use_existing_vault" { + type = bool + description = "Use existing vault" + default = true +} +variable "new_vault_display_name" { + type = string + description = "Display name of the key vault" + default = "" +} +variable "vault_id" { + description = "The vault where the database ADMIN password will be stored" + type = string + default = "none" +} +# Encryption key to be used when storing the ADMIN password +variable "key_id" { + description = "Encryption key used for storing the password" + type = string + default = "none" +} + +# ------------------------- Environment variables required for Document Extraction Application ----------------------------- # + +# The following variables will be used by deployment. +variable "data_science_project_compartment_id" { + description = "Compartment in which Data Science Project is present" + type = string +} +variable "project_ocid" { + default = "ocid1.datascienceproject.oc1.iad.amaaaaaav66vvniadk4ecmjg7lhz65s54ulqdi4bcbk3u6e26bsjg4mekyjq" +} + +variable "log_group_ocid" { + default = "ocid1.loggroup.oc1.iad.amaaaaaav66vvnia76nyddgo3e6jfchcn6jhi7zvn7do3tlxh6ug4ye2hhgq" +} +variable "log_ocid" { + default = "ocid1.log.oc1.iad.amaaaaaav66vvnias7eplqdggtirvefa7nc3vhg2gjlekblrwmylo35hpvta" +} + +variable "shape" { + default = "VM.Standard.E5.Flex" +} + +variable "container_shape" { + default = "CI.Standard.E4.Flex" +} +variable "memory_in_gbs" { + default = 16 +} +variable "ocpus" { + default = 1 +} + +variable "container_display_name" { + default = "AI Document Converter Instance" +} + +# The following variables are for deployment +variable "deployment_display_name" { + default = "AI Document Converter Deployment" +} +variable "deployment_type" { + default = "SINGLE_MODEL" +} +variable "deployment_bandwidth_mbps" { + default = 10 +} +variable "deployment_instance_count" { + default = 1 +} + +# The following variables are for container instance + +variable "multimodal_llm_provider" { + default = "genai" +} +variable "genai_compartment_ocid" { + default = "ocid1.tenancy.oc1..aaaaaaaahzy3x4boh7ipxyft2rowu2xeglvanlfewudbnueugsieyuojkldq" +} +variable "multimodal_model_name" { + default = "openai.gpt-4.1-mini" +} +variable "multimodal_model_endpoint" { + default = "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com" +} +variable "multimodal_max_output_token" { + default = 8192 +} +variable "prompt_version" { + default = 3 +} + + +# locals variables +locals { + vcn_id = (var.create_new_vcn ? oci_core_vcn.aih_vcn[0].id : var.existing_vcn_id) + app_subnet_id = (var.create_new_vcn ? oci_core_subnet.app_oci_core_subnet[0].id : var.existing_app_subnet_id) + api_gw_subnet_id = (var.create_new_vcn ? oci_core_subnet.api_gw_oci_core_subnet[0].id : var.existing_api_gw_subnet_id) + + image = "iad.ocir.io/ociodscdev/document-converter:1.0.1" + digest = "sha256:2b07ac9bb1aeea99828a6ca8e1615edf083ff931f67e74295e51bb571bb49124" + model_id = "ocid1.datasciencemodel.oc1.iad.amaaaaaav66vvnia44764hnygt3td7wme7ly3jrjupaal42m4uqcfebnkg2q" + md_desc = "Deployment for PDF to Markdown Converter" +} + + diff --git a/ai-hub/ai-document-converter/policies/terraform/vault.tf b/ai-hub/ai-document-converter/policies/terraform/vault.tf new file mode 100644 index 00000000..32365b03 --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/vault.tf @@ -0,0 +1,37 @@ +resource "oci_kms_vault" "app_vault" { + compartment_id = var.vault_compartment_id + display_name = var.new_vault_display_name + vault_type = "DEFAULT" + count = var.use_existing_vault ? 0 : 1 +} + +resource "oci_kms_key" "app_key" { + compartment_id = var.vault_compartment_id + display_name = "${var.new_vault_display_name}-key" + key_shape { + algorithm = "AES" + length = 256 + } + management_endpoint = oci_kms_vault.app_vault[0].management_endpoint + count = var.use_existing_vault ? 0 : 1 +} + +resource "oci_vault_secret" "idcs_app_client_secret" { + depends_on = [ + oci_kms_vault.app_vault, + oci_kms_key.app_key + ] + #Required + compartment_id = var.vault_compartment_id + secret_content { + #Required + content_type = "BASE64" + + #Optional + content = base64encode(oci_identity_domains_app.ai_application_confidential_app.client_secret) + name = "idcs_client_secret_${formatdate("MMDDhhmm", timestamp())}" + } + secret_name = "idcs_client_secret_${formatdate("MMDDhhmm", timestamp())}" + vault_id = var.use_existing_vault ? var.vault_id : oci_kms_vault.app_vault[0].id + key_id = var.use_existing_vault ? var.key_id : oci_kms_key.app_key[0].id +} \ No newline at end of file diff --git a/ai-hub/ai-translation/policies/terraform/api_gateway.tf b/ai-hub/ai-translation/policies/terraform/api_gateway.tf new file mode 100644 index 00000000..0c234a69 --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/api_gateway.tf @@ -0,0 +1,127 @@ +# API Gateway +resource "oci_apigateway_gateway" "ai_application_oci_apigateway_gateway" { + compartment_id = var.compartment_id + display_name = "ai_application_api_gw_${random_string.randomstring.result}" + endpoint_type = "PUBLIC" + response_cache_details { + type = "NONE" + } + subnet_id = local.api_gw_subnet_id +} + +# API Gateway Deployments +resource "oci_apigateway_deployment" "ai_application_apigateway_deployment" { + compartment_id = var.compartment_id + display_name = "api-deployment${random_string.randomstring.result}" + gateway_id = oci_apigateway_gateway.ai_application_oci_apigateway_gateway.id + path_prefix = "/" + specification { + logging_policies { + execution_log { + log_level = "INFO" + } + } + request_policies { + authentication { + is_anonymous_access_allowed = "true" + token_auth_scheme = "Bearer" + token_header = "token" + type = "TOKEN_AUTHENTICATION" + validation_failure_policy { + client_details { + type = "VALIDATION_BLOCK" + } + response_type = "CODE" + scopes = ["openid"] + source_uri_details { + type = "VALIDATION_BLOCK" + } + type = "OAUTH2" + use_cookies_for_intermediate_steps = "true" + use_cookies_for_session = "true" + } + validation_policy { + additional_validation_policy { + issuers = ["https://identity.oraclecloud.com/"] + } + client_details { + client_id = oci_identity_domains_app.ai_application_confidential_app.name + client_secret_id = oci_vault_secret.idcs_app_client_secret.id + client_secret_version_number = "1" + type = "CUSTOM" + } + max_cache_duration_in_hours = "1" + source_uri_details { + type = "DISCOVERY_URI" + uri = "${data.oci_identity_domain.application_identity_domain.url}/.well-known/openid-configuration" + } + type = "REMOTE_DISCOVERY" + } + } + mutual_tls { + is_verified_certificate_required = "false" + } + } + routes { + backend { + type = "OAUTH2_LOGOUT_BACKEND" + } + logging_policies { + } + methods = ["GET"] + path = "/logout" + } + routes { + backend { + status = "200" + type = "STOCK_RESPONSE_BACKEND" + } + logging_policies { + } + methods = ["ANY"] + path = "/token" + response_policies { + header_transformations { + set_headers { + items { + if_exists = "OVERWRITE" + name = "token" + values = ["$${request.auth[id_token]}"] + } + items { + if_exists = "OVERWRITE" + name = "x-csrf-token" + values = ["$${request.auth[apigw_csrf_token]}"] + } + } + } + } + } + routes { + backend { + connect_timeout_in_seconds = "60" + is_ssl_verify_disabled = "false" + read_timeout_in_seconds = "10" + send_timeout_in_seconds = "10" + type = "HTTP_BACKEND" + url = "http://${data.oci_core_vnic.ai_application_container_instance_vnic.private_ip_address}:8080/$${request.path[req]}" + } + logging_policies { + } + methods = ["ANY"] + path = "/{req*}" + response_policies { + header_transformations { + set_headers { + items { + name = "X-CSRF-TOKEN" + values = ["$${request.auth[apigw_csrf_token]}"] + if_exists = "OVERWRITE" + } + } + } + } + } + } +} + diff --git a/ai-hub/ai-translation/policies/terraform/container_instances.tf b/ai-hub/ai-translation/policies/terraform/container_instances.tf new file mode 100644 index 00000000..b023bedd --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/container_instances.tf @@ -0,0 +1,44 @@ +resource "oci_container_instances_container_instance" "ai_container_instance" { + #Required + availability_domain = var.availability_domain + compartment_id = var.compartment_id + containers { + #Required + image_url = local.image + + #Optional + environment_variables = { + # OCI GenAI Service + MODEL_BACKEND = var.model_backend, + MODEL_NAME = var.model_name, + MODEL_URL = var.model_url + OPENAI_API_KEY = var.openai_api_key, + NUM_WORKERS = var.num_workers, + TASK_STORE = "TMPDIR", + LOG_DIR = var.translation_log_dir, + PROJECT_COMPARTMENT_OCID = var.compartment_ocid, + PROCESSING_JOB_OCID = oci_datascience_job.ai_job.id, + OCI_CACHE_ENDPOINT = var.oci_cache_endpoint, + BACKEND_MD_URL = oci_datascience_model_deployment.ai_deployment.model_deployment_url, + http_proxy = "http://10.68.69.53:80", + https_proxy = "http://10.68.69.53:80", + no_proxy = "oraclecloud.com,artifactory.oci.oraclecorp.com,artifacthub-tip.oraclecorp.com,oraclecorp.com,oc-test.com,127.0.0.1,localhost,100.100.84.201,100.126.5.5,10.89.228.16,10.242.12.81,10.89.228.14,169.254.169.254" + } + } + shape = var.container_shape + shape_config { + #Required + ocpus = var.ocpus + + #Optional + memory_in_gbs = var.memory_in_gbs + } + vnics { + #Required + subnet_id = local.app_subnet_id + # private_ip = var.container_instance_private_ip + } + + #Optional + display_name = var.container_display_name +} diff --git a/ai-hub/ai-translation/policies/terraform/datascience_job.tf b/ai-hub/ai-translation/policies/terraform/datascience_job.tf new file mode 100644 index 00000000..f5525ca7 --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/datascience_job.tf @@ -0,0 +1,49 @@ +# Job +resource "oci_datascience_job" "ai_job" { + # Required + display_name = var.job_display_name + description = local.job_desc + compartment_id = var.compartment_id + project_id = var.project_ocid + + job_configuration_details { + job_type = "DEFAULT" + environment_variables = { + MODEL_BACKEND = var.model_backend, + MODEL_NAME = var.model_name, + MODEL_URL = var.model_url + OPENAI_API_KEY = var.openai_api_key, + } + } + job_infrastructure_configuration_details { + job_infrastructure_type = "STANDALONE" + shape_name = var.shape + job_shape_config_details { + memory_in_gbs = var.memory_in_gbs + ocpus = var.ocpus + } + block_storage_size_in_gbs = 50 + # subnet_id = var.subnet_app + subnet_id = local.app_subnet_id + } + + job_environment_configuration_details { + job_environment_type = "OCIR_CONTAINER" + image = local.image + image_digest = local.digest + entrypoint = local.job_entrypoint + cmd = local.job_cmd + } + + # Logging + job_log_configuration_details { + enable_logging = true + log_group_id = var.log_group_ocid + log_id = var.log_ocid + } + + timeouts { + delete = "2m" + } + +} \ No newline at end of file diff --git a/ai-hub/ai-translation/policies/terraform/datasources.tf b/ai-hub/ai-translation/policies/terraform/datasources.tf new file mode 100644 index 00000000..a3282382 --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/datasources.tf @@ -0,0 +1,25 @@ +data "oci_core_services" "all_oci_services" { + filter { + name = "name" + values = ["All .* Services In Oracle Services Network"] + regex = true + } +} + +data "oci_identity_availability_domains" "get_availability_domains" { + compartment_id = var.compartment_ocid +} + +data "oci_identity_domain" "application_identity_domain" { + domain_id = trimspace(var.identity_domain_id) + lifecycle { + precondition { + condition = var.identity_domain_id != null + error_message = "Existing domain id must be provided when using an existing domain." + } + } +} + +data "oci_core_vnic" "ai_application_container_instance_vnic" { + vnic_id = oci_container_instances_container_instance.ai_container_instance.vnics[0].vnic_id +} \ No newline at end of file diff --git a/ai-hub/ai-translation/policies/terraform/identity_app.tf b/ai-hub/ai-translation/policies/terraform/identity_app.tf new file mode 100644 index 00000000..0f9b76f1 --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/identity_app.tf @@ -0,0 +1,20 @@ +resource "oci_identity_domains_app" "ai_application_confidential_app" { + based_on_template { + value = "CustomWebAppTemplateId" + well_known_id = "CustomWebAppTemplateId" + } + client_type = "confidential" + description = "Confidential Application for AI Translation Application" + display_name = "ai__translation_application_confidential_app_${random_string.randomstring.result}" + schemas = ["urn:ietf:params:scim:schemas:oracle:idcs:App"] + allowed_operations = ["introspect"] + idcs_endpoint = data.oci_identity_domain.application_identity_domain.url + active = true + is_oauth_client = true + bypass_consent = true + allowed_grants = ["authorization_code", "client_credentials", "urn:ietf:params:oauth:grant-type:jwt-bearer", "implicit"] + all_url_schemes_allowed = true + redirect_uris = ["https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/api/docs", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/playground/", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/playground/translate"] + post_logout_redirect_uris = ["https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/"] + audience = oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname +} \ No newline at end of file diff --git a/ai-hub/ai-translation/policies/terraform/model_deployment.tf b/ai-hub/ai-translation/policies/terraform/model_deployment.tf new file mode 100644 index 00000000..4d518409 --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/model_deployment.tf @@ -0,0 +1,68 @@ +# Model deployment with custom network and scaling policy type = FIXED SIZE +resource "oci_datascience_model_deployment" "ai_deployment" { + # Required + display_name = var.deployment_display_name + description = local.md_desc + compartment_id = var.compartment_id + project_id = var.project_ocid + + model_deployment_configuration_details { + deployment_type = var.deployment_type + model_configuration_details { + # Required + instance_configuration { + instance_shape_name = var.shape + model_deployment_instance_shape_config_details { + memory_in_gbs = var.memory_in_gbs + ocpus = var.ocpus + } + # Required for custom networking + # subnet_id = var.subnet_ocid + subnet_id = local.app_subnet_id + } + model_id = local.model_id + bandwidth_mbps = var.deployment_bandwidth_mbps + scaling_policy { + instance_count = var.deployment_instance_count + policy_type = "FIXED_SIZE" + } + } + + environment_configuration_details { + image = local.image + image_digest = local.digest + environment_configuration_type = "OCIR_CONTAINER" + # Environment variables are customized based on the AI app. + environment_variables = { + # OCI GenAI Service + MODEL_BACKEND = var.model_backend, + MODEL_NAME = var.model_name, + MODEL_URL = var.model_url + OPENAI_API_KEY = var.openai_api_key, + NUM_WORKERS = var.num_workers, + TASK_STORE = "TMPDIR", + LOG_DIR = var.translation_log_dir, + PROJECT_COMPARTMENT_OCID = var.compartment_id, + PROCESSING_JOB_OCID = oci_datascience_job.ai_job.id, + OCI_CACHE_ENDPOINT = var.oci_cache_endpoint, + MODEL_DEPLOY_CUSTOM_ENDPOINTS = "[{\"endpointURI\": \"/api/languages\", \"httpMethods\": [\"GET\"]}, {\"endpointURI\": \"/api/batch\", \"httpMethods\": [\"POST\"]}, {\"endpointURI\": \"/api/task\", \"httpMethods\": [\"GET\"]}, {\"endpointURI\": \"/api/translate\", \"httpMethods\": [\"GET\", \"POST\"]}, {\"endpointURI\": \"/api/translate\", \"httpMethods\": [\"POST\"], \"streaming\": true}]", + http_proxy = "http://10.68.69.53:80", + https_proxy = "http://10.68.69.53:80", + no_proxy = "oraclecloud.com,artifactory.oci.oraclecorp.com,artifacthub-tip.oraclecorp.com,oraclecorp.com,oc-test.com,127.0.0.1,localhost,100.100.84.201,100.126.5.5,10.89.228.16,10.242.12.81,10.89.228.14,169.254.169.254" + } + } + } + + # Logging, use the same log group and log ocid to reduce the variables. + category_log_details { + access { + log_group_id = var.log_group_ocid + log_id = var.log_ocid + } + predict { + log_group_id = var.log_group_ocid + log_id = var.log_ocid + } + } + +} \ No newline at end of file diff --git a/ai-hub/ai-translation/policies/terraform/network.tf b/ai-hub/ai-translation/policies/terraform/network.tf new file mode 100644 index 00000000..ac88543e --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/network.tf @@ -0,0 +1,210 @@ +# VCN +resource "oci_core_vcn" "aih_vcn" { + count = var.create_new_vcn ? 1 : 0 + cidr_block = var.vcn_cidr + compartment_id = var.compartment_id + display_name = var.vcn_display_name +} + +# Gateways/ Route Table Enties for Public Subnet which will contain Load Balancer +resource "oci_core_internet_gateway" "igw" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "public-subnet-igw" + enabled = true +} + +resource "oci_core_route_table" "public_subnet_route_table" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "Public Subnet Route Table" + route_rules { + destination = "0.0.0.0/0" + network_entity_id = oci_core_internet_gateway.igw[0].id + destination_type = "CIDR_BLOCK" + } +} + +# NAT Gateway and Service gateway for private subnet which will conatain the instance serving Ui Application + +resource "oci_core_nat_gateway" "nat_gatway" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "private-subnet-nat-gtw" +} + +resource "oci_core_service_gateway" "service_gateway" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "private-subnet-service-gtw" + services { + service_id = lookup(data.oci_core_services.all_oci_services.services[0], "id") + } +} + +resource "oci_core_route_table" "private_subnet_route_table" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "Private Subnet Route Table" + route_rules { + destination = "0.0.0.0/0" + network_entity_id = oci_core_nat_gateway.nat_gatway[0].id + destination_type = "CIDR_BLOCK" + } + route_rules { + destination = lookup(data.oci_core_services.all_oci_services.services[0], "cidr_block") + destination_type = "SERVICE_CIDR_BLOCK" + network_entity_id = oci_core_service_gateway.service_gateway[0].id + description = "Terraformed - Auto-generated at Service Gateway creation: All Services in region to Service Gateway" + } +} + +#Security List for Public Subnet + +resource "oci_core_security_list" "public_subnet_security_list" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "PublicSubnetSL" + + # Inbound Rules + ingress_security_rules { + protocol = "6" # TCP + source = "0.0.0.0/0" + source_type = "CIDR_BLOCK" + tcp_options { + min = 80 + max = 80 + } + description = "Allow HTTP traffic" + } + + ingress_security_rules { + // allow all SSH + protocol = "6" + source = "0.0.0.0/0" + + source_type = "CIDR_BLOCK" + tcp_options { + min = 22 + max = 22 + } + } + + ingress_security_rules { + protocol = "6" # TCP + source = "0.0.0.0/0" + source_type = "CIDR_BLOCK" + tcp_options { + min = 443 + max = 443 + } + description = "Allow HTTPS traffic" + } + + # ingress_security_rules { + # protocol = 6 + # source = "0.0.0.0/0" + + # source_type = "CIDR_BLOCK" + # tcp_options { + # max = 8080 + # min = 8080 + # } + # } + + # Outbound Rules + egress_security_rules { + protocol = "all" + destination = "0.0.0.0/0" + description = "Allow all outbound traffic" + } +} + +resource "oci_core_security_list" "private_subnet_security_list" { + count = var.create_new_vcn ? 1 : 0 + compartment_id = var.compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + display_name = "PrivateSubnetSL" + egress_security_rules { + destination = "0.0.0.0/0" + protocol = "all" + } + # HTTP Traffic + ingress_security_rules { + protocol = 6 + source = "0.0.0.0/0" + + source_type = "CIDR_BLOCK" + tcp_options { + max = 80 + min = 80 + } + } + # SSH Access + ingress_security_rules { + protocol = 6 + source = "0.0.0.0/0" + + source_type = "CIDR_BLOCK" + tcp_options { + max = 22 + min = 22 + } + } + # Allowing Traffic on port 8080 + ingress_security_rules { + protocol = 6 + source = "0.0.0.0/0" + + source_type = "CIDR_BLOCK" + tcp_options { + max = 8080 + min = 8080 + } + } + # Allowing Traffic on port 8000 + ingress_security_rules { + protocol = 6 + source = "0.0.0.0/0" + + source_type = "CIDR_BLOCK" + tcp_options { + max = 8000 + min = 8000 + } + } +} + +# Create Subnets + +resource "oci_core_subnet" "app_oci_core_subnet" { + count = var.create_new_vcn ? 1 : 0 + display_name = "app-subnet-${formatdate("MMDDhhmm", timestamp())}" + cidr_block = var.app_subnet_cidr + compartment_id = var.compartment_id + vcn_id = oci_core_vcn.aih_vcn[0].id + prohibit_internet_ingress = true + prohibit_public_ip_on_vnic = true + security_list_ids = [oci_core_security_list.private_subnet_security_list[0].id] + route_table_id = oci_core_route_table.private_subnet_route_table[0].id +} + +resource "oci_core_subnet" "api_gw_oci_core_subnet" { + count = var.create_new_vcn ? 1 : 0 + cidr_block = var.api_gw_subnet_cidr + compartment_id = var.compartment_id + display_name = "api-gw-subnet-${formatdate("MMDDhhmm", timestamp())}" + vcn_id = oci_core_vcn.aih_vcn[0].id + prohibit_internet_ingress = false + prohibit_public_ip_on_vnic = false + security_list_ids = [oci_core_security_list.public_subnet_security_list[0].id] + route_table_id = oci_core_route_table.public_subnet_route_table[0].id +} + + diff --git a/ai-hub/ai-translation/policies/terraform/output.tf b/ai-hub/ai-translation/policies/terraform/output.tf new file mode 100644 index 00000000..4b31efdd --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/output.tf @@ -0,0 +1,4 @@ +output "app_url" { + description = "Application URL" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}" +} \ No newline at end of file diff --git a/ai-hub/ai-translation/policies/terraform/provider.tf b/ai-hub/ai-translation/policies/terraform/provider.tf new file mode 100644 index 00000000..76475433 --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/provider.tf @@ -0,0 +1,8 @@ +terraform { + required_version = ">= 1.0" +} + +provider "oci" { + region = var.region + tenancy_ocid = var.tenancy_ocid +} \ No newline at end of file diff --git a/ai-hub/ai-translation/policies/terraform/random.tf b/ai-hub/ai-translation/policies/terraform/random.tf new file mode 100644 index 00000000..3e16cc0e --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/random.tf @@ -0,0 +1,4 @@ +resource "random_string" "randomstring" { + length = 10 + special = false +} \ No newline at end of file diff --git a/ai-hub/ai-translation/policies/terraform/schema.yaml b/ai-hub/ai-translation/policies/terraform/schema.yaml new file mode 100644 index 00000000..27032208 --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/schema.yaml @@ -0,0 +1,221 @@ +title: "AI Solutions - Translation Application" +stackDescription: Deploy AI Translation Application with Authentication with OCI IAM via Resource Manager Stack +description: "Deploy AI Translation Application with Authentication with OCI IAM via Resource Manager Stack" +schemaVersion: 1.1.0 +version: "20190404" +locale: "en" + +variableGroups: + - title: Hide constants and internal variables + visible: false + variables: + - tenancy_ocid + - compartment_ocid + - current_user_ocid + - region + - shape + - model_backend + - model_name + - model_url + - openai_api_key + - translation_log_dir + - num_workers + - vcn_display_name + - multimodal_model_name + - deployment_type + - deployment_bandwidth_mbps + - deployment_instance_count + - model_backend + - model_name + - model_url + - oci_cache_endpoint + - openai_api_key + - translation_log_dir + - num_workers + + - title: "General Configuration" + variables: + - compartment_id + - availability_domain + - title: "Network" + variables: + - create_new_vcn + - existing_vcn_id + - vcn_cidr + - existing_app_subnet_id + - app_subnet_cidr + - existing_api_gw_subnet_id + - api_gw_subnet_cidr + - title: "Authentication Configuration" + variables: + - identity_domain_id + - use_existing_vault + - new_vault_display_name + - vault_id + - key_id + - title: "Application Container Instance Configurations" + variables: + - container_shape + - memory_in_gbs + - ocpus + +variables: + # General Configuration + compartment_id: + type: oci:identity:compartment:id + required: true + title: Compartment Id + description: The compartment in which to create all the resources. + default: compartment_ocid + availability_domain: + type: oci:identity:availabilitydomain:name + required: true + title: Availability domain + description: The availability domain in which to create all Compute Instance resources. + dependsOn: + compartmentId: ${compartment_id} + #Network Configuration + create_new_vcn: + type: boolean + required: true + title: Create New VCN, Subnet, NAT Gateway, Internet Gateway, etc. for the application + default: true + existing_vcn_id: + type: oci:core:vcn:id + required: true + title: Select to VCN + visible: + not: + - create_new_vcn + dependsOn: + compartmentId: ${compartment_id} + vcn_cidr: + type: string + required: true + title: VCN IPv4 CIDR Blocks + description: This VCN will be used for all resources created by the stack. + default: "10.1.0.0/16" + pattern: "^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\/(3[0-2]|[1-2]?[0-9])$" + visible: create_new_vcn + existing_app_subnet_id: + type: oci:core:subnet:id + required: true + title: Select the application subnet + dependsOn: + compartmentId: ${compartment_id} + vcnId: ${existing_vcn_id} + hidePublicSubnet: true + visible: + not: + - create_new_vcn + app_subnet_cidr: + type: string + required: true + title: Application Subnet IPv4 CIDR Blocks + description: The container instances running the application will be created in this subnet. + default: "10.1.1.0/24" + pattern: "^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\/(3[0-2]|[1-2]?[0-9])$" + visible: create_new_vcn + existing_api_gw_subnet_id: + type: oci:core:subnet:id + required: true + title: Select the API Gateway subnet + dependsOn: + compartmentId: ${compartment_id} + vcnId: ${existing_vcn_id} + hidePublicSubnet: false + visible: + not: + - create_new_vcn + api_gw_subnet_cidr: + type: string + required: true + title: API Gateway Subnet IPv4 CIDR Blocks + description: API Gateway will be created in this subnet. + pattern: "^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\/(3[0-2]|[1-2]?[0-9])$" + default: "10.1.2.0/24" + visible: create_new_vcn + #Application Configuration + identity_domain_id: + type: oci:identity:domains:id + required: true + title: Identity domain + description: Identity Domain in which confidential integrated application needs to be created + visible: true + dependsOn: + compartmentId: ${compartment_id} + # Vault Configuration + use_existing_vault: + type: boolean + title: Use an existing key vault + required: true + default: true + description: This vault will be used to store client secret of identity application used by API Gateway for Authentication. + new_vault_display_name: + type: string + title: Key vault display name + description: A user-friendly name to help you easily identify the resource. + required: true + visible: + not: + - use_existing_vault + vault_id: + type: oci:kms:vault:id + required: true + title: Vault + description: Choose an existing vault used to store the client secret. + dependsOn: + compartmentId: ${compartment_id} + visible: + and: + - use_existing_vault + key_id: + type: oci:kms:key:id + required: true + title: Encryption key + description: This key will be used to encrypt the sensitive information stored as vault secrets. + dependsOn: + compartmentId: ${compartment_id} + vaultId: ${vault_id} + visible: + and: + - use_existing_vault + # Container instances configuration + container_shape: + type: enum + required: true + title: Container instance shape + description: A shape is a template that determines the number of OCPUs, amount of memory, and other resources that are allocated to a container instance. + default: "CI.Standard.E4.Flex" + enum: + - CI.Standard.E3.Flex + - CI.Standard.E4.Flex + memory_in_gbs: + type: number + required: true + title: Memory (GB) + default: 16 + minimum: 1 + maximum: 1024 + description: Min - 1 GB or a value matching the number of OCPUs, whichever is greater. Max - 64 GB per OCPU, up to 1024 GB total + ocpus: + type: number + required: true + title: OCPU + description: Min - 1 OCPU. Max - 64 OCPU + default: 1 + minimum: 1 + maximum: 64 + +outputGroups: + - title: "Application URL" + outputs: + - app_url + +outputs: + app_url: + type: link + title: "Playground UI URL" + visible: true + + diff --git a/ai-hub/ai-translation/policies/terraform/timeout.tf b/ai-hub/ai-translation/policies/terraform/timeout.tf new file mode 100644 index 00000000..5516967b --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/timeout.tf @@ -0,0 +1,4 @@ +// Timeout to make sure the network is complete before start creating the containers +resource "time_sleep" "wait_seconds" { + create_duration = "150s" +} \ No newline at end of file diff --git a/ai-hub/ai-translation/policies/terraform/variables.tf b/ai-hub/ai-translation/policies/terraform/variables.tf new file mode 100644 index 00000000..6997cd26 --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/variables.tf @@ -0,0 +1,175 @@ +variable "tenancy_ocid" {} +variable "compartment_ocid" {} +variable "region" {} + +variable "compartment_id" { + description = "The selected compartment, by default the compartment in which stack is created" + type = string +} + +variable "availability_domain" { + description = "Availabiliy domain" + type = string +} +# Network configuration CIDR + +variable "create_new_vcn" { + type = bool + default = true +} +variable "existing_vcn_id" { + type = string + default = "" +} +variable "vcn_display_name" { + default = "ai-solutions-vcn" +} +variable "vcn_cidr" { + type = string + default = "10.1.0.0/16" +} +variable "existing_app_subnet_id" { + type = string + default = "" +} +variable "app_subnet_cidr" { + type = string + default = "10.1.2.0/24" +} +variable "existing_api_gw_subnet_id" { + type = string + default = "" +} +variable "api_gw_subnet_cidr" { + type = string + default = "10.1.1.0/24" +} + +#IDCS Configuration +variable "identity_domain_id" { + type = string + default = "" +} + +#Vault Configuration to Store Identity App Client Secret +variable "use_existing_vault" { + type = bool + description = "Use existing vault" + default = true +} +variable "new_vault_display_name" { + type = string + description = "Display name of the key vault" + default = "" +} +variable "vault_id" { + description = "The vault where the database ADMIN password will be stored" + type = string + default = "none" +} +# Encryption key to be used when storing the ADMIN password +variable "key_id" { + description = "Encryption key used for storing the password" + type = string + default = "none" +} + +# ------------------------- Environment variables required for Document Extraction Application ----------------------------- # + +# The following variables will be used by deployment. +variable "project_ocid" { + default = "ocid1.datascienceproject.oc1.iad.amaaaaaav66vvniaklsknycfb6fso64knuk36egpsg3j5vasn3sveiuvdmna" +} + +variable "log_group_ocid" { + default = "ocid1.loggroup.oc1.iad.amaaaaaav66vvniaidjweu7sgg5qgx7yzri5yb4xw3qnqsg6szl2xdh7scka" +} +variable "log_ocid" { + default = "ocid1.log.oc1.iad.amaaaaaav66vvnia3h4o6otedz4lz23zex6z2pei6yjqszb7zdfswaa5srca" +} + +variable "shape" { + default = "VM.Standard.E5.Flex" +} + +variable "container_shape" { + default = "CI.Standard.E4.Flex" +} +variable "memory_in_gbs" { + default = 16 +} +variable "ocpus" { + default = 1 +} + +# The following variables are for job +variable "job_display_name" { + default = "AI Translation Job" +} + +variable "container_display_name" { + default = "AI Translation Container" +} + +# The following variables are for deployment +variable "deployment_display_name" { + default = "AI Translation Deployment" +} +variable "deployment_type" { + default = "SINGLE_MODEL" +} +variable "deployment_bandwidth_mbps" { + default = 10 +} +variable "deployment_instance_count" { + default = 1 +} + +# The following variables are for container instance + +variable "model_backend" { + default = "GenAI" +} + +variable "model_name" { + default = "meta.llama-3.3-70b-instruct" +} + +variable "model_url" { + default = "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com" +} + +variable "oci_cache_endpoint" { + # default = "" + default = "aaav66vvniax2viamc6jbwfeujiowpxnuu7kioiyfyqwgdptkwthq2q-p.redis.us-ashburn-1.oci.oraclecloud.com" +} + +variable "openai_api_key" { + default = "sk-123456789" +} + +variable "translation_log_dir" { + default = "oci://a_bucket_for_qq@ociodscdev/data/translation/logs" +} + +variable "num_workers" { + default = "1" +} + + +# locals variables +locals { + vcn_id = (var.create_new_vcn ? oci_core_vcn.aih_vcn[0].id : var.existing_vcn_id) + app_subnet_id = (var.create_new_vcn ? oci_core_subnet.app_oci_core_subnet[0].id : var.existing_app_subnet_id) + api_gw_subnet_id = (var.create_new_vcn ? oci_core_subnet.api_gw_oci_core_subnet[0].id : var.existing_api_gw_subnet_id) + + image = "iad.ocir.io/ociodscdev/ai_translation:1.35" + digest = "sha256:9de28d33b7419b7f9ff42a6c2ad6792e904c3c815949f090e35e688cb23553fc" + job_desc = "Job for batch translation" + job_entrypoint = ["python"] + job_cmd = ["/opt/app/batch.py"] + model_id = "ocid1.datasciencemodel.oc1.iad.amaaaaaav66vvniazwx42xndxz3kfemfpwht3unc3ib33tscln462gmuwiyq" + md_desc = "Deployment for AI translation Application" +} + + diff --git a/ai-hub/ai-translation/policies/terraform/vault.tf b/ai-hub/ai-translation/policies/terraform/vault.tf new file mode 100644 index 00000000..992e3ece --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/vault.tf @@ -0,0 +1,37 @@ +resource "oci_kms_vault" "app_vault" { + compartment_id = var.compartment_id + display_name = var.new_vault_display_name + vault_type = "DEFAULT" + count = var.use_existing_vault ? 0 : 1 +} + +resource "oci_kms_key" "app_key" { + compartment_id = var.compartment_id + display_name = "${var.new_vault_display_name}-key" + key_shape { + algorithm = "AES" + length = 256 + } + management_endpoint = oci_kms_vault.app_vault[0].management_endpoint + count = var.use_existing_vault ? 0 : 1 +} + +resource "oci_vault_secret" "idcs_app_client_secret" { + depends_on = [ + oci_kms_vault.app_vault, + oci_kms_key.app_key + ] + #Required + compartment_id = var.compartment_id + secret_content { + #Required + content_type = "BASE64" + + #Optional + content = base64encode(oci_identity_domains_app.ai_application_confidential_app.client_secret) + name = "idcs_client_secret_${formatdate("MMDDhhmm", timestamp())}" + } + secret_name = "idcs_client_secret_${formatdate("MMDDhhmm", timestamp())}" + vault_id = var.use_existing_vault ? var.vault_id : oci_kms_vault.app_vault[0].id + key_id = var.use_existing_vault ? var.key_id : oci_kms_key.app_key[0].id +} \ No newline at end of file From 4a135e5adbd7b0249e8e40d0c2c3447e67ea23f1 Mon Sep 17 00:00:00 2001 From: Vipul Date: Thu, 4 Sep 2025 10:06:35 -0700 Subject: [PATCH 2/6] update stack --- .github/workflows/stack.yml | 68 +++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/.github/workflows/stack.yml b/.github/workflows/stack.yml index 3cf1e92f..87e7749a 100644 --- a/.github/workflows/stack.yml +++ b/.github/workflows/stack.yml @@ -17,32 +17,72 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create stacks id: create_stacks run: | + set -euo pipefail + RELEASE=$(cat VERSION) + # oci-ods-aqua STACKNAME=oci-ods-aqua STACK_FILES="ai-quick-actions/policies/terraform/*" - RELEASE=$(cat VERSION) - ASSETS+="${STACKNAME}.zip" echo "::group::Processing $STACKNAME" - zip -r ${STACKNAME}-stack.zip $STACK_FILES || { printf '\nâ›” Unable to create %s stack.\n'; exit 1; } - cp ${STACKNAME}-stack.zip ${STACKNAME}.zip || { printf '\nâ›” Unable to create %s stack.\n'; exit 1; } + zip -r ${STACKNAME}-stack.zip $STACK_FILES + cp ${STACKNAME}-stack.zip ${STACKNAME}.zip + echo "::endgroup::" + + # ai-document-converter-app + DOC_CONVERTER_STACKNAME=ai-document-converter + DOC_CONVERTER_FILES="ai-hub/ai-document-converter/policies/terraform/*" + echo "::group::Packaging $DOC_CONVERTER_STACKNAME" + zip -r ${DOC_CONVERTER_STACKNAME}-stack.zip $DOC_CONVERTER_FILES + cp ${DOC_CONVERTER_STACKNAME}-stack.zip ${DOC_CONVERTER_STACKNAME}.zip + echo "::endgroup::" + + # ai-translation-app + TRANSLATION_STACKNAME=ai-translation + TRANSLATION_FILES="ai-hub/ai-translation/policies/terraform/*" + echo "::group::Packaging $TRANSLATION_STACKNAME" + zip -r ${TRANSLATION_STACKNAME}-stack.zip $TRANSLATION_FILES + cp ${TRANSLATION_STACKNAME}-stack.zip ${TRANSLATION_STACKNAME}.zip echo "::endgroup::" - echo "::set-output name=assets::$ASSETS" - echo "::set-output name=release::$RELEASE" - echo "::set-output name=prefix::$STACKNAME" + + ASSETS="${STACKNAME}.zip ${DOC_CONVERTER_STACKNAME}.zip ${TRANSLATION_STACKNAME}.zip" + + { + echo "assets=${ASSETS}" + echo "release=${RELEASE}" + echo "aqua=${STACKNAME}" + echo "ai_document_converter=${DOC_CONVERTER_STACKNAME}" + echo "ai_translation=${TRANSLATION_STACKNAME}" + } >> $GITHUB_OUTPUT - name: Prepare Release Notes + shell: bash run: | - # - printf '%s\n' '${{ steps.create_stacks.outputs.prefix }} Stack - v${{ steps.create_stacks.outputs.release }}' >release.md - printf '%s\n' '' '## [![Deploy to Oracle Cloud][magic_button]][magic_stack]' >>release.md - printf '%s\n' '' '' >>release.md - printf '%s\n' '' '[magic_button]: https://oci-resourcemanager-plugin.plugins.oci.oraclecloud.com/latest/deploy-to-oracle-cloud.svg' >>release.md - printf '%s\n' '' '[magic_stack]: https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/${{ github.repository }}/releases/download/${{ steps.create_stacks.outputs.release }}/${{ steps.create_stacks.outputs.prefix }}.zip' >>release.md + rel="${{ steps.create_stacks.outputs.release }}" + aqua="${{ steps.create_stacks.outputs.aqua }}" + ai_document_converter="${{ steps.create_stacks.outputs.ai_document_converter }}" + ai_translation="${{ steps.create_stacks.outputs.ai_translation }}" + + { + printf '# Stacks - v%s\n\n' "$rel" + printf '### %s\n' "$aqua" + printf '## [![Deploy to Oracle Cloud][magic_button]][magic_stack_aqua]\n\n' + + printf '### %s\n' "$ai_document_converter" + printf '## [![Deploy to Oracle Cloud][magic_button]][magic_stack_ai_document_converter]\n\n' + + printf '### %s\n' "$ai_translation" + printf '## [![Deploy to Oracle Cloud][magic_button]][magic_stack_ai_translation]\n\n' + + printf '[magic_button]: https://oci-resourcemanager-plugin.plugins.oci.oraclecloud.com/latest/deploy-to-oracle-cloud.svg\n' + printf '[magic_stack_aqua]: https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/${{ github.repository }}/releases/download/%s/%s.zip\n' "$rel" "$aqua" + printf '[magic_stack_ai_document_converter]: https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/${{ github.repository }}/releases/download/%s/%s.zip\n' "$rel" "$ai_document_converter" + printf '[magic_stack_ai_translation]: https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/${{ github.repository }}/releases/download/%s/%s.zip\n' "$rel" "$ai_translation" + } > release.md - name: Create Release run: gh release create ${{ steps.create_stacks.outputs.release }} --generate-notes -F release.md ${{ steps.create_stacks.outputs.assets }} From 9833098f19d88e3a873ee38a90ebd9181eef096d Mon Sep 17 00:00:00 2001 From: Vipul Date: Mon, 15 Sep 2025 10:52:51 -0700 Subject: [PATCH 3/6] update policies --- .../policies/terraform/api_gateway.tf | 12 +- .../policies/terraform/container_instances.tf | 2 +- .../policies/terraform/identity_app.tf | 4 +- .../policies/terraform/model.tf | 43 +++ .../policies/terraform/model_deployment.tf | 4 +- .../policies/terraform/schema.yaml | 39 +-- .../policies/terraform/variables.tf | 24 +- .../policies/terraform/api_gateway.tf | 20 +- .../policies/terraform/container_instances.tf | 25 +- .../policies/terraform/datascience_job.tf | 10 +- .../policies/terraform/identity_app.tf | 2 +- .../policies/terraform/model.tf | 43 +++ .../policies/terraform/model_deployment.tf | 27 +- .../policies/terraform/network.tf | 31 +- .../policies/terraform/output.tf | 41 ++- .../policies/terraform/schema.yaml | 271 +++++++++++++++--- .../policies/terraform/variables.tf | 38 ++- .../policies/terraform/vault.tf | 6 +- 18 files changed, 485 insertions(+), 157 deletions(-) create mode 100644 ai-hub/ai-document-converter/policies/terraform/model.tf create mode 100644 ai-hub/ai-translation/policies/terraform/model.tf diff --git a/ai-hub/ai-document-converter/policies/terraform/api_gateway.tf b/ai-hub/ai-document-converter/policies/terraform/api_gateway.tf index 846b30bd..e97e0f33 100644 --- a/ai-hub/ai-document-converter/policies/terraform/api_gateway.tf +++ b/ai-hub/ai-document-converter/policies/terraform/api_gateway.tf @@ -40,6 +40,7 @@ resource "oci_apigateway_deployment" "ai_application_apigateway_deployment" { type = "OAUTH2" use_cookies_for_intermediate_steps = "true" use_cookies_for_session = "true" + max_expiry_duration_in_hours = 1 } validation_policy { additional_validation_policy { @@ -111,13 +112,18 @@ resource "oci_apigateway_deployment" "ai_application_apigateway_deployment" { } methods = ["ANY"] path = "/{req*}" - response_policies { + request_policies { header_transformations { set_headers { items { - name = "X-CSRF-TOKEN" - values = ["$${request.auth[apigw_csrf_token]}"] if_exists = "OVERWRITE" + name = "id_token" + values = ["$${request.auth[id_token]}"] + } + items { + if_exists = "OVERWRITE" + name = "Host" + values = ["$${request.host}"] } } } diff --git a/ai-hub/ai-document-converter/policies/terraform/container_instances.tf b/ai-hub/ai-document-converter/policies/terraform/container_instances.tf index 1f332b46..ae4ea383 100644 --- a/ai-hub/ai-document-converter/policies/terraform/container_instances.tf +++ b/ai-hub/ai-document-converter/policies/terraform/container_instances.tf @@ -1,7 +1,7 @@ resource "oci_container_instances_container_instance" "ai_container_instance" { #Required availability_domain = var.availability_domain - compartment_id = var.compartment_id + compartment_id = var.vcn_compartment_id containers { #Required image_url = local.image diff --git a/ai-hub/ai-document-converter/policies/terraform/identity_app.tf b/ai-hub/ai-document-converter/policies/terraform/identity_app.tf index 838af102..3167274f 100644 --- a/ai-hub/ai-document-converter/policies/terraform/identity_app.tf +++ b/ai-hub/ai-document-converter/policies/terraform/identity_app.tf @@ -14,7 +14,7 @@ resource "oci_identity_domains_app" "ai_application_confidential_app" { bypass_consent = true allowed_grants = ["authorization_code", "client_credentials", "urn:ietf:params:oauth:grant-type:jwt-bearer", "implicit"] all_url_schemes_allowed = true - redirect_uris = ["https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/html/convert", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/api/docs", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/callback"] + redirect_uris = ["https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui","https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/gradio", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/playground","https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/docs", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/callback"] post_logout_redirect_uris = ["https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/"] audience = oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname -} \ No newline at end of file +} diff --git a/ai-hub/ai-document-converter/policies/terraform/model.tf b/ai-hub/ai-document-converter/policies/terraform/model.tf new file mode 100644 index 00000000..ba9f98ba --- /dev/null +++ b/ai-hub/ai-document-converter/policies/terraform/model.tf @@ -0,0 +1,43 @@ +# dummy model artifact (zip) built from inline files +data "archive_file" "model_zip" { + type = "zip" + output_path = "${path.module}/model-artifact.zip" + + # minimal runtime.yaml expected by OCI model artifacts + source { + filename = "runtime.yaml" + content = <<-YAML + kind: generic + type: python + entryPoint: "score.py" + pythonVersion: "3.11" + YAML + } + + # Trivial scorer stub + source { + filename = "score.py" + content = <<-PY + def predict(data): + # no-op dummy implementation + return {"ok": True, "echo": data} + PY + } +} + +# dummy Model catalog entry with artifact +resource "oci_datascience_model" "ai_model" { + compartment_id = var.data_science_project_compartment_id + project_id = var.project_ocid + display_name = var.model_display_name + description = local.model_desc + + # Upload artifact inline (ZIP created above) + model_artifact = data.archive_file.model_zip.output_path + artifact_content_length = data.archive_file.model_zip.output_size + artifact_content_disposition = "attachment; filename=model-artifact.zip" + + retention_setting { + archive_after_days = 365 + } +} diff --git a/ai-hub/ai-document-converter/policies/terraform/model_deployment.tf b/ai-hub/ai-document-converter/policies/terraform/model_deployment.tf index 5f943844..52611634 100644 --- a/ai-hub/ai-document-converter/policies/terraform/model_deployment.tf +++ b/ai-hub/ai-document-converter/policies/terraform/model_deployment.tf @@ -20,7 +20,7 @@ resource "oci_datascience_model_deployment" "ai_deployment" { # subnet_id = var.subnet_ocid subnet_id = local.app_subnet_id } - model_id = local.model_id + model_id = oci_datascience_model.ai_model.id bandwidth_mbps = var.deployment_bandwidth_mbps scaling_policy { instance_count = var.deployment_instance_count @@ -41,7 +41,7 @@ resource "oci_datascience_model_deployment" "ai_deployment" { MAX_OUTPUT_TOKEN = var.multimodal_max_output_token GENAI_COMPARTMENT_OCID = var.genai_compartment_ocid PROMPT_VERSION = var.prompt_version, - MODEL_DEPLOY_CUSTOM_ENDPOINTS = "[{\"endpointURI\": \"/apis\", \"httpMethods\": [\"GET\"]}, {\"endpointURI\": \"/convert\", \"httpMethods\": [\"POST\"]}, {\"endpointURI\": \"/convert/file\", \"httpMethods\": [\"POST\"]}]" + MODEL_DEPLOY_CUSTOM_ENDPOINTS = "[{\"endpointURI\": \"/api/list\", \"httpMethods\": [\"GET\"]}, {\"endpointURI\": \"/api/convert\", \"httpMethods\": [\"POST\"]}, {\"endpointURI\": \"/api/convert/file\", \"httpMethods\": [\"POST\"]}]" } } } diff --git a/ai-hub/ai-document-converter/policies/terraform/schema.yaml b/ai-hub/ai-document-converter/policies/terraform/schema.yaml index 23b20054..c396a60f 100644 --- a/ai-hub/ai-document-converter/policies/terraform/schema.yaml +++ b/ai-hub/ai-document-converter/policies/terraform/schema.yaml @@ -1,6 +1,6 @@ -title: "AI Solutions - PDF to Markdown Application" -stackDescription: Deploy PDF to Markdown Application with Authentication with OCI IAM via Resource Manager Stack -description: "Deploy PDF to Markdown Application with Authentication with OCI IAM via Resource Manager Stack" +title: "AI Solution - PDF to markdown conversion Solution" +stackDescription: Stack to deploy an AI-powered solution that converts PDFs into clean, structured Markdown, enabling seamless integration with Retrieval-Augmented Generation (RAG) workflows and enterprise AI applications. +description: "AI-powered solution that converts PDFs into clean, structured Markdown, enabling seamless integration with Retrieval-Augmented Generation (RAG) workflows and enterprise AI applications." schemaVersion: 1.1.0 version: "20190404" locale: "en" @@ -15,40 +15,28 @@ variableGroups: - region - shape - model_backend - - model_name + - model_display_name - model_url - - openai_api_key - - translation_log_dir - - num_workers - - vcn_display_name - multimodal_model_name - deployment_type - deployment_bandwidth_mbps - deployment_instance_count - model_backend - - model_name - - model_url - - oci_cache_endpoint - - openai_api_key - - translation_log_dir - - num_workers - multimodal_llm_provider - multimodal_max_output_token - multimodal_model_endpoint - prompt_version - - log_group_ocid - - log_ocid - title: "General Configuration" variables: - compartment_id - availability_domain - - data_science_project_ocid - title: "Network" variables: - vcn_compartment_id - create_new_vcn - existing_vcn_id + - vcn_display_name - vcn_cidr - existing_app_subnet_id - app_subnet_cidr @@ -113,6 +101,12 @@ variables: - create_new_vcn dependsOn: compartmentId: ${vcn_compartment_id} + vcn_display_name: + type: string + required: true + title: VCN Display Name + description: This VCN will be used for all resources created by the stack. + visible: create_new_vcn vcn_cidr: type: string required: true @@ -264,11 +258,22 @@ variables: type: oci:identity:compartment:id required: true title: Gen AI Compartment OCID + default: tenancy_ocid deployment_display_name: type: string title: Model Deployment display name description: A user-friendly name to help you easily identify the Model Deployment resource in Data Science Project. required: true + log_group_ocid: + type: string + title: Log Group ocid + description: Log Group Ocid where logs will be stored + required: false + log_ocid: + type: string + title: Log ocid + description: Log ocid where where logs needs to be stored + required: false outputGroups: diff --git a/ai-hub/ai-document-converter/policies/terraform/variables.tf b/ai-hub/ai-document-converter/policies/terraform/variables.tf index a9aef70a..e1876df9 100644 --- a/ai-hub/ai-document-converter/policies/terraform/variables.tf +++ b/ai-hub/ai-document-converter/policies/terraform/variables.tf @@ -94,14 +94,17 @@ variable "data_science_project_compartment_id" { type = string } variable "project_ocid" { - default = "ocid1.datascienceproject.oc1.iad.amaaaaaav66vvniadk4ecmjg7lhz65s54ulqdi4bcbk3u6e26bsjg4mekyjq" + type = string + description = "Data Science project in which resources needs to be created" } variable "log_group_ocid" { - default = "ocid1.loggroup.oc1.iad.amaaaaaav66vvnia76nyddgo3e6jfchcn6jhi7zvn7do3tlxh6ug4ye2hhgq" + type = string + description = "Log Group Ocid where logs will be stored" } variable "log_ocid" { - default = "ocid1.log.oc1.iad.amaaaaaav66vvnias7eplqdggtirvefa7nc3vhg2gjlekblrwmylo35hpvta" + type = string + description = "Log ocid where where logs needs to be stored" } variable "shape" { @@ -118,6 +121,10 @@ variable "ocpus" { default = 1 } +variable "model_display_name" { + default = "AI Document Converter Model" +} + variable "container_display_name" { default = "AI Document Converter Instance" } @@ -142,7 +149,8 @@ variable "multimodal_llm_provider" { default = "genai" } variable "genai_compartment_ocid" { - default = "ocid1.tenancy.oc1..aaaaaaaahzy3x4boh7ipxyft2rowu2xeglvanlfewudbnueugsieyuojkldq" + type = string + description = "Gen AI Compartment OCID" } variable "multimodal_model_name" { default = "openai.gpt-4.1-mini" @@ -164,10 +172,8 @@ locals { app_subnet_id = (var.create_new_vcn ? oci_core_subnet.app_oci_core_subnet[0].id : var.existing_app_subnet_id) api_gw_subnet_id = (var.create_new_vcn ? oci_core_subnet.api_gw_oci_core_subnet[0].id : var.existing_api_gw_subnet_id) - image = "iad.ocir.io/ociodscdev/document-converter:1.0.1" - digest = "sha256:2b07ac9bb1aeea99828a6ca8e1615edf083ff931f67e74295e51bb571bb49124" - model_id = "ocid1.datasciencemodel.oc1.iad.amaaaaaav66vvnia44764hnygt3td7wme7ly3jrjupaal42m4uqcfebnkg2q" + image = "dsmc://ai-document-converter:0.1.0-dev.15" + digest = "sha256:01bf5e53ea01377c63c42c1c30c12f4885de94b39e3a1b4edf5d195bfdfa0c9d" + model_desc = "Data Science Model for PDF to Markdown Converter Deployment" md_desc = "Deployment for PDF to Markdown Converter" } - - diff --git a/ai-hub/ai-translation/policies/terraform/api_gateway.tf b/ai-hub/ai-translation/policies/terraform/api_gateway.tf index 0c234a69..3638a9d7 100644 --- a/ai-hub/ai-translation/policies/terraform/api_gateway.tf +++ b/ai-hub/ai-translation/policies/terraform/api_gateway.tf @@ -1,6 +1,6 @@ # API Gateway resource "oci_apigateway_gateway" "ai_application_oci_apigateway_gateway" { - compartment_id = var.compartment_id + compartment_id = var.compartment_ocid display_name = "ai_application_api_gw_${random_string.randomstring.result}" endpoint_type = "PUBLIC" response_cache_details { @@ -11,7 +11,7 @@ resource "oci_apigateway_gateway" "ai_application_oci_apigateway_gateway" { # API Gateway Deployments resource "oci_apigateway_deployment" "ai_application_apigateway_deployment" { - compartment_id = var.compartment_id + compartment_id = var.compartment_ocid display_name = "api-deployment${random_string.randomstring.result}" gateway_id = oci_apigateway_gateway.ai_application_oci_apigateway_gateway.id path_prefix = "/" @@ -31,6 +31,7 @@ resource "oci_apigateway_deployment" "ai_application_apigateway_deployment" { client_details { type = "VALIDATION_BLOCK" } + logout_path = "/logout" response_type = "CODE" scopes = ["openid"] source_uri_details { @@ -101,8 +102,8 @@ resource "oci_apigateway_deployment" "ai_application_apigateway_deployment" { backend { connect_timeout_in_seconds = "60" is_ssl_verify_disabled = "false" - read_timeout_in_seconds = "10" - send_timeout_in_seconds = "10" + read_timeout_in_seconds = "120" + send_timeout_in_seconds = "120" type = "HTTP_BACKEND" url = "http://${data.oci_core_vnic.ai_application_container_instance_vnic.private_ip_address}:8080/$${request.path[req]}" } @@ -110,13 +111,18 @@ resource "oci_apigateway_deployment" "ai_application_apigateway_deployment" { } methods = ["ANY"] path = "/{req*}" - response_policies { + request_policies { header_transformations { set_headers { items { - name = "X-CSRF-TOKEN" - values = ["$${request.auth[apigw_csrf_token]}"] if_exists = "OVERWRITE" + name = "id_token" + values = ["$${request.auth[id_token]}"] + } + items { + if_exists = "OVERWRITE" + name = "Host" + values = ["$${request.host}"] } } } diff --git a/ai-hub/ai-translation/policies/terraform/container_instances.tf b/ai-hub/ai-translation/policies/terraform/container_instances.tf index b023bedd..9ea38d69 100644 --- a/ai-hub/ai-translation/policies/terraform/container_instances.tf +++ b/ai-hub/ai-translation/policies/terraform/container_instances.tf @@ -1,7 +1,7 @@ resource "oci_container_instances_container_instance" "ai_container_instance" { #Required availability_domain = var.availability_domain - compartment_id = var.compartment_id + compartment_id = var.vcn_compartment_id containers { #Required image_url = local.image @@ -9,20 +9,17 @@ resource "oci_container_instances_container_instance" "ai_container_instance" { #Optional environment_variables = { # OCI GenAI Service - MODEL_BACKEND = var.model_backend, - MODEL_NAME = var.model_name, + MODEL_BACKEND = var.model_backend + MODEL_NAME = var.model_name MODEL_URL = var.model_url - OPENAI_API_KEY = var.openai_api_key, - NUM_WORKERS = var.num_workers, - TASK_STORE = "TMPDIR", - LOG_DIR = var.translation_log_dir, - PROJECT_COMPARTMENT_OCID = var.compartment_ocid, - PROCESSING_JOB_OCID = oci_datascience_job.ai_job.id, - OCI_CACHE_ENDPOINT = var.oci_cache_endpoint, - BACKEND_MD_URL = oci_datascience_model_deployment.ai_deployment.model_deployment_url, - http_proxy = "http://10.68.69.53:80", - https_proxy = "http://10.68.69.53:80", - no_proxy = "oraclecloud.com,artifactory.oci.oraclecorp.com,artifacthub-tip.oraclecorp.com,oraclecorp.com,oc-test.com,127.0.0.1,localhost,100.100.84.201,100.126.5.5,10.89.228.16,10.242.12.81,10.89.228.14,169.254.169.254" + OPENAI_API_KEY = var.openai_api_key + NUM_WORKERS = var.num_workers + TASK_STORE = "TMPDIR" + LOG_DIR = var.translation_log_dir + PROJECT_COMPARTMENT_OCID = var.data_science_project_compartment_id + PROCESSING_JOB_OCID = oci_datascience_job.ai_job.id + OCI_CACHE_ENDPOINT = var.oci_cache_endpoint + BACKEND_MD_URL = oci_datascience_model_deployment.ai_deployment.model_deployment_url } } shape = var.container_shape diff --git a/ai-hub/ai-translation/policies/terraform/datascience_job.tf b/ai-hub/ai-translation/policies/terraform/datascience_job.tf index f5525ca7..7dbef4f1 100644 --- a/ai-hub/ai-translation/policies/terraform/datascience_job.tf +++ b/ai-hub/ai-translation/policies/terraform/datascience_job.tf @@ -3,16 +3,16 @@ resource "oci_datascience_job" "ai_job" { # Required display_name = var.job_display_name description = local.job_desc - compartment_id = var.compartment_id + compartment_id = var.data_science_project_compartment_id project_id = var.project_ocid job_configuration_details { job_type = "DEFAULT" environment_variables = { - MODEL_BACKEND = var.model_backend, - MODEL_NAME = var.model_name, + MODEL_BACKEND = var.model_backend + MODEL_NAME = var.model_name MODEL_URL = var.model_url - OPENAI_API_KEY = var.openai_api_key, + OPENAI_API_KEY = var.openai_api_key } } job_infrastructure_configuration_details { @@ -30,7 +30,7 @@ resource "oci_datascience_job" "ai_job" { job_environment_configuration_details { job_environment_type = "OCIR_CONTAINER" image = local.image - image_digest = local.digest + # image_digest = local.digest entrypoint = local.job_entrypoint cmd = local.job_cmd } diff --git a/ai-hub/ai-translation/policies/terraform/identity_app.tf b/ai-hub/ai-translation/policies/terraform/identity_app.tf index 0f9b76f1..6851a03b 100644 --- a/ai-hub/ai-translation/policies/terraform/identity_app.tf +++ b/ai-hub/ai-translation/policies/terraform/identity_app.tf @@ -14,7 +14,7 @@ resource "oci_identity_domains_app" "ai_application_confidential_app" { bypass_consent = true allowed_grants = ["authorization_code", "client_credentials", "urn:ietf:params:oauth:grant-type:jwt-bearer", "implicit"] all_url_schemes_allowed = true - redirect_uris = ["https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/api/docs", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/playground/", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/playground/translate"] + redirect_uris = ["https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/","https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/playground", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/docs", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/"] post_logout_redirect_uris = ["https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/"] audience = oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname } \ No newline at end of file diff --git a/ai-hub/ai-translation/policies/terraform/model.tf b/ai-hub/ai-translation/policies/terraform/model.tf new file mode 100644 index 00000000..ba9f98ba --- /dev/null +++ b/ai-hub/ai-translation/policies/terraform/model.tf @@ -0,0 +1,43 @@ +# dummy model artifact (zip) built from inline files +data "archive_file" "model_zip" { + type = "zip" + output_path = "${path.module}/model-artifact.zip" + + # minimal runtime.yaml expected by OCI model artifacts + source { + filename = "runtime.yaml" + content = <<-YAML + kind: generic + type: python + entryPoint: "score.py" + pythonVersion: "3.11" + YAML + } + + # Trivial scorer stub + source { + filename = "score.py" + content = <<-PY + def predict(data): + # no-op dummy implementation + return {"ok": True, "echo": data} + PY + } +} + +# dummy Model catalog entry with artifact +resource "oci_datascience_model" "ai_model" { + compartment_id = var.data_science_project_compartment_id + project_id = var.project_ocid + display_name = var.model_display_name + description = local.model_desc + + # Upload artifact inline (ZIP created above) + model_artifact = data.archive_file.model_zip.output_path + artifact_content_length = data.archive_file.model_zip.output_size + artifact_content_disposition = "attachment; filename=model-artifact.zip" + + retention_setting { + archive_after_days = 365 + } +} diff --git a/ai-hub/ai-translation/policies/terraform/model_deployment.tf b/ai-hub/ai-translation/policies/terraform/model_deployment.tf index 4d518409..74855fe9 100644 --- a/ai-hub/ai-translation/policies/terraform/model_deployment.tf +++ b/ai-hub/ai-translation/policies/terraform/model_deployment.tf @@ -3,7 +3,7 @@ resource "oci_datascience_model_deployment" "ai_deployment" { # Required display_name = var.deployment_display_name description = local.md_desc - compartment_id = var.compartment_id + compartment_id = var.data_science_project_compartment_id project_id = var.project_ocid model_deployment_configuration_details { @@ -20,7 +20,7 @@ resource "oci_datascience_model_deployment" "ai_deployment" { # subnet_id = var.subnet_ocid subnet_id = local.app_subnet_id } - model_id = local.model_id + model_id = oci_datascience_model.ai_model.id bandwidth_mbps = var.deployment_bandwidth_mbps scaling_policy { instance_count = var.deployment_instance_count @@ -30,25 +30,22 @@ resource "oci_datascience_model_deployment" "ai_deployment" { environment_configuration_details { image = local.image - image_digest = local.digest + # image_digest = local.digest environment_configuration_type = "OCIR_CONTAINER" # Environment variables are customized based on the AI app. environment_variables = { # OCI GenAI Service - MODEL_BACKEND = var.model_backend, - MODEL_NAME = var.model_name, + MODEL_BACKEND = var.model_backend + MODEL_NAME = var.model_name MODEL_URL = var.model_url - OPENAI_API_KEY = var.openai_api_key, - NUM_WORKERS = var.num_workers, + OPENAI_API_KEY = var.openai_api_key + NUM_WORKERS = var.num_workers TASK_STORE = "TMPDIR", - LOG_DIR = var.translation_log_dir, - PROJECT_COMPARTMENT_OCID = var.compartment_id, - PROCESSING_JOB_OCID = oci_datascience_job.ai_job.id, - OCI_CACHE_ENDPOINT = var.oci_cache_endpoint, - MODEL_DEPLOY_CUSTOM_ENDPOINTS = "[{\"endpointURI\": \"/api/languages\", \"httpMethods\": [\"GET\"]}, {\"endpointURI\": \"/api/batch\", \"httpMethods\": [\"POST\"]}, {\"endpointURI\": \"/api/task\", \"httpMethods\": [\"GET\"]}, {\"endpointURI\": \"/api/translate\", \"httpMethods\": [\"GET\", \"POST\"]}, {\"endpointURI\": \"/api/translate\", \"httpMethods\": [\"POST\"], \"streaming\": true}]", - http_proxy = "http://10.68.69.53:80", - https_proxy = "http://10.68.69.53:80", - no_proxy = "oraclecloud.com,artifactory.oci.oraclecorp.com,artifacthub-tip.oraclecorp.com,oraclecorp.com,oc-test.com,127.0.0.1,localhost,100.100.84.201,100.126.5.5,10.89.228.16,10.242.12.81,10.89.228.14,169.254.169.254" + LOG_DIR = var.translation_log_dir + PROJECT_COMPARTMENT_OCID = var.data_science_project_compartment_id + PROCESSING_JOB_OCID = oci_datascience_job.ai_job.id + OCI_CACHE_ENDPOINT = var.oci_cache_endpoint + MODEL_DEPLOY_CUSTOM_ENDPOINTS = "[{\"endpointURI\": \"/api/languages\", \"httpMethods\": [\"GET\"]}, {\"endpointURI\": \"/api/batch\", \"httpMethods\": [\"POST\"]}, {\"endpointURI\": \"/api/task\", \"httpMethods\": [\"GET\"]}, {\"endpointURI\": \"/api/translate\", \"httpMethods\": [\"GET\", \"POST\"]}, {\"endpointURI\": \"/api/translate\", \"httpMethods\": [\"POST\"], \"streaming\": true}]" } } } diff --git a/ai-hub/ai-translation/policies/terraform/network.tf b/ai-hub/ai-translation/policies/terraform/network.tf index ac88543e..f06a322a 100644 --- a/ai-hub/ai-translation/policies/terraform/network.tf +++ b/ai-hub/ai-translation/policies/terraform/network.tf @@ -2,14 +2,14 @@ resource "oci_core_vcn" "aih_vcn" { count = var.create_new_vcn ? 1 : 0 cidr_block = var.vcn_cidr - compartment_id = var.compartment_id + compartment_id = var.vcn_compartment_id display_name = var.vcn_display_name } # Gateways/ Route Table Enties for Public Subnet which will contain Load Balancer resource "oci_core_internet_gateway" "igw" { count = var.create_new_vcn ? 1 : 0 - compartment_id = var.compartment_id + compartment_id = var.vcn_compartment_id vcn_id = oci_core_vcn.aih_vcn[0].id display_name = "public-subnet-igw" enabled = true @@ -17,7 +17,7 @@ resource "oci_core_internet_gateway" "igw" { resource "oci_core_route_table" "public_subnet_route_table" { count = var.create_new_vcn ? 1 : 0 - compartment_id = var.compartment_id + compartment_id = var.vcn_compartment_id vcn_id = oci_core_vcn.aih_vcn[0].id display_name = "Public Subnet Route Table" route_rules { @@ -31,14 +31,14 @@ resource "oci_core_route_table" "public_subnet_route_table" { resource "oci_core_nat_gateway" "nat_gatway" { count = var.create_new_vcn ? 1 : 0 - compartment_id = var.compartment_id + compartment_id = var.vcn_compartment_id vcn_id = oci_core_vcn.aih_vcn[0].id display_name = "private-subnet-nat-gtw" } resource "oci_core_service_gateway" "service_gateway" { count = var.create_new_vcn ? 1 : 0 - compartment_id = var.compartment_id + compartment_id = var.vcn_compartment_id vcn_id = oci_core_vcn.aih_vcn[0].id display_name = "private-subnet-service-gtw" services { @@ -48,7 +48,7 @@ resource "oci_core_service_gateway" "service_gateway" { resource "oci_core_route_table" "private_subnet_route_table" { count = var.create_new_vcn ? 1 : 0 - compartment_id = var.compartment_id + compartment_id = var.vcn_compartment_id vcn_id = oci_core_vcn.aih_vcn[0].id display_name = "Private Subnet Route Table" route_rules { @@ -68,7 +68,7 @@ resource "oci_core_route_table" "private_subnet_route_table" { resource "oci_core_security_list" "public_subnet_security_list" { count = var.create_new_vcn ? 1 : 0 - compartment_id = var.compartment_id + compartment_id = var.vcn_compartment_id vcn_id = oci_core_vcn.aih_vcn[0].id display_name = "PublicSubnetSL" @@ -107,17 +107,6 @@ resource "oci_core_security_list" "public_subnet_security_list" { description = "Allow HTTPS traffic" } - # ingress_security_rules { - # protocol = 6 - # source = "0.0.0.0/0" - - # source_type = "CIDR_BLOCK" - # tcp_options { - # max = 8080 - # min = 8080 - # } - # } - # Outbound Rules egress_security_rules { protocol = "all" @@ -128,7 +117,7 @@ resource "oci_core_security_list" "public_subnet_security_list" { resource "oci_core_security_list" "private_subnet_security_list" { count = var.create_new_vcn ? 1 : 0 - compartment_id = var.compartment_id + compartment_id = var.vcn_compartment_id vcn_id = oci_core_vcn.aih_vcn[0].id display_name = "PrivateSubnetSL" egress_security_rules { @@ -187,7 +176,7 @@ resource "oci_core_subnet" "app_oci_core_subnet" { count = var.create_new_vcn ? 1 : 0 display_name = "app-subnet-${formatdate("MMDDhhmm", timestamp())}" cidr_block = var.app_subnet_cidr - compartment_id = var.compartment_id + compartment_id = var.vcn_compartment_id vcn_id = oci_core_vcn.aih_vcn[0].id prohibit_internet_ingress = true prohibit_public_ip_on_vnic = true @@ -198,7 +187,7 @@ resource "oci_core_subnet" "app_oci_core_subnet" { resource "oci_core_subnet" "api_gw_oci_core_subnet" { count = var.create_new_vcn ? 1 : 0 cidr_block = var.api_gw_subnet_cidr - compartment_id = var.compartment_id + compartment_id = var.vcn_compartment_id display_name = "api-gw-subnet-${formatdate("MMDDhhmm", timestamp())}" vcn_id = oci_core_vcn.aih_vcn[0].id prohibit_internet_ingress = false diff --git a/ai-hub/ai-translation/policies/terraform/output.tf b/ai-hub/ai-translation/policies/terraform/output.tf index 4b31efdd..d8acde74 100644 --- a/ai-hub/ai-translation/policies/terraform/output.tf +++ b/ai-hub/ai-translation/policies/terraform/output.tf @@ -1,4 +1,39 @@ -output "app_url" { - description = "Application URL" +output "base_url" { + description = "Application Base URL" value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}" -} \ No newline at end of file +} + +output "mcp_endpoint" { + description = "MCP Endpoint" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}mcp" +} + +output "playground_ui" { + description = "Playground UI" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}playground/" +} + +output "api_reference" { + description = "API Reference" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}api/docs" +} + +output "api_schema" { + description = "API Schema" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}api/schema" +} + +output "api_endpoint_default" { + description = "API Endpoint - Translate" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}api/translate" +} + +output "api_endpoint_batch" { + description = "API Endpoint - Batch Translation Job" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}api/batch" +} + +output "api_endpoint_list_languages" { + description = "API Endpoint - Supported Languages" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}api/languages" +} diff --git a/ai-hub/ai-translation/policies/terraform/schema.yaml b/ai-hub/ai-translation/policies/terraform/schema.yaml index 27032208..071d0629 100644 --- a/ai-hub/ai-translation/policies/terraform/schema.yaml +++ b/ai-hub/ai-translation/policies/terraform/schema.yaml @@ -1,6 +1,6 @@ title: "AI Solutions - Translation Application" -stackDescription: Deploy AI Translation Application with Authentication with OCI IAM via Resource Manager Stack -description: "Deploy AI Translation Application with Authentication with OCI IAM via Resource Manager Stack" +stackDescription: Stack to deploy an AI-powered solution that translate text from one language into another language +description: "AI-powered solution that translate text from one language into another language" schemaVersion: 1.1.0 version: "20190404" locale: "en" @@ -13,34 +13,31 @@ variableGroups: - compartment_ocid - current_user_ocid - region - - shape - - model_backend - - model_name - - model_url - - openai_api_key - - translation_log_dir - - num_workers - vcn_display_name - - multimodal_model_name - deployment_type - - deployment_bandwidth_mbps - - deployment_instance_count + + - title: "General Configuration" + variables: + - compartment_ocid + - availability_domain + - shape + - project_ocid + - log_group_ocid + - log_ocid + - title: "Application Configurations" + variables: - model_backend - model_name - model_url - - oci_cache_endpoint - openai_api_key + - oci_cache_endpoint - translation_log_dir - - num_workers - - - title: "General Configuration" - variables: - - compartment_id - - availability_domain - - title: "Network" + - title: "Network Configurations" variables: + - vcn_compartment_id - create_new_vcn - existing_vcn_id + - vcn_display_name - vcn_cidr - existing_app_subnet_id - app_subnet_cidr @@ -48,33 +45,115 @@ variableGroups: - api_gw_subnet_cidr - title: "Authentication Configuration" variables: + - identity_domain_compartment_id - identity_domain_id + - vault_compartment_id - use_existing_vault - new_vault_display_name - vault_id - key_id - - title: "Application Container Instance Configurations" + - title: "Model Deployment Configurations" variables: + - deployment_display_name + - deployment_type + - deployment_bandwidth_mbps + - deployment_instance_count + - num_workers + - title: "Job Configurations" + variables: + - job_display_name + - title: "Container Instance Configurations" + variables: + - container_display_name - container_shape - memory_in_gbs - ocpus + - title: "Application Configuration" + variables: + - genai_compartment_ocid + - data_science_project_compartment_id + - project_ocid + - deployment_display_name variables: - # General Configuration - compartment_id: + # General + compartment_ocid: type: oci:identity:compartment:id required: true - title: Compartment Id + title: Compartment ID description: The compartment in which to create all the resources. - default: compartment_ocid availability_domain: type: oci:identity:availabilitydomain:name required: true - title: Availability domain + title: Availability Domain description: The availability domain in which to create all Compute Instance resources. dependsOn: - compartmentId: ${compartment_id} - #Network Configuration + compartmentId: ${compartment_ocid} + shape: + type: oci:core:instanceshape:name + required: true + title: Shape Name + description: The instance shape for jobs and model deployments. + dependsOn: + compartmentId: ${compartment_ocid} + project_ocid: + type: oci:ods:project:id + required: true + title: Data Science Project + description: The Data Science Project for creating model deployments and jobs. + dependsOn: + compartmentId: ${compartment_ocid} + log_group_ocid: + type: string + required: true + title: Log Group OCID + description: Log Group OCID. + log_ocid: + type: string + required: true + title: Log OCID + description: Log OCID. + # Application + model_backend: + type: enum + required: true + title: Model API Backend + description: The API spec/backend for the LLM. + enum: + - GenAI + - OpenAI + model_name: + type: string + required: true + title: Model Name + description: The LLM model name or model ID. + model_url: + type: string + required: false + title: Service Endpoint or Model Endpoint + description: The service endpoint for OCI generative AI or base URL endpoint of the LLM. + openai_api_key: + type: string + required: false + title: API KEY for OpenAI Backend + description: API Key for authenticating with the OpenAI backend (if applicable). + oci_cache_endpoint: + type: string + required: false + title: OCI Cache Endpoint + description: The endpoint for the OCI cache cluster. + translation_log_dir: + type: string + required: false + title: Translation Log Location + description: Object storage location to store translation logs. + # Network + vcn_compartment_id: + type: oci:identity:compartment:id + required: true + title: VCN Compartment Id + description: Compartment in which VCN, Subnets needs to be created or present. + default: compartment_ocid create_new_vcn: type: boolean required: true @@ -83,12 +162,18 @@ variables: existing_vcn_id: type: oci:core:vcn:id required: true - title: Select to VCN + title: Select a VCN visible: not: - create_new_vcn dependsOn: - compartmentId: ${compartment_id} + compartmentId: ${vcn_compartment_id} + vcn_display_name: + type: string + required: true + title: VCN Display Name + description: This VCN will be used for all resources created by the stack. + visible: create_new_vcn vcn_cidr: type: string required: true @@ -102,7 +187,7 @@ variables: required: true title: Select the application subnet dependsOn: - compartmentId: ${compartment_id} + compartmentId: ${vcn_compartment_id} vcnId: ${existing_vcn_id} hidePublicSubnet: true visible: @@ -121,7 +206,7 @@ variables: required: true title: Select the API Gateway subnet dependsOn: - compartmentId: ${compartment_id} + compartmentId: ${vcn_compartment_id} vcnId: ${existing_vcn_id} hidePublicSubnet: false visible: @@ -136,6 +221,12 @@ variables: default: "10.1.2.0/24" visible: create_new_vcn #Application Configuration + identity_domain_compartment_id: + type: oci:identity:compartment:id + required: true + title: Identity Domain Compartment Id + description: Compartment in which Identity Domain is present. + default: compartment_ocid identity_domain_id: type: oci:identity:domains:id required: true @@ -143,8 +234,14 @@ variables: description: Identity Domain in which confidential integrated application needs to be created visible: true dependsOn: - compartmentId: ${compartment_id} + compartmentId: ${identity_domain_compartment_id} # Vault Configuration + vault_compartment_id: + type: oci:identity:compartment:id + required: true + title: Vault Compartment Id + description: Compartment in which Vault is present. + default: compartment_ocid use_existing_vault: type: boolean title: Use an existing key vault @@ -165,7 +262,7 @@ variables: title: Vault description: Choose an existing vault used to store the client secret. dependsOn: - compartmentId: ${compartment_id} + compartmentId: ${vault_compartment_id} visible: and: - use_existing_vault @@ -175,12 +272,48 @@ variables: title: Encryption key description: This key will be used to encrypt the sensitive information stored as vault secrets. dependsOn: - compartmentId: ${compartment_id} + compartmentId: ${vault_compartment_id} vaultId: ${vault_id} visible: and: - use_existing_vault - # Container instances configuration + # Model Deployment + deployment_display_name: + type: string + required: true + title: Model Deployment Display Name + description: Display name for the model deployment resource. + deployment_bandwidth_mbps: + type: number + required: true + default: 10 + minimum: 10 + title: Deployment Bandwidth (Mbps) + description: Bandwidth in Mbps for the deployment. + deployment_instance_count: + type: number + required: true + default: 1 + minimum: 1 + title: Deployment Instance Count + description: Number of instances for the deployment. + num_workers: + type: number + required: false + title: Number of Workers + description: Number of worker processes for the job/service. + # Job + job_display_name: + type: string + required: false + title: Job Display Name + description: Display name for the translation job. + # Container Instances + container_display_name: + type: string + required: true + title: Container Display Name + description: A user-friendly name to help you easily identify the container instance resource. container_shape: type: enum required: true @@ -206,16 +339,72 @@ variables: default: 1 minimum: 1 maximum: 64 + #Application Configuration + data_science_project_compartment_id: + type: oci:identity:compartment:id + required: true + title: Data Science Project Compartment Id + description: Compartment in which Data Science Project is present. + default: compartment_ocid + project_ocid: + type: oci:ods:project:id + required: true + title: Select Data Science Project + dependsOn: + compartmentId: ${data_science_project_compartment_id} + log_group_ocid: + type: string + title: Log Group ocid + description: Log Group Ocid where logs will be stored + required: false + log_ocid: + type: string + title: Log ocid + description: Log ocid where where logs needs to be stored + required: false outputGroups: - - title: "Application URL" + - title: "Application URLs" outputs: - - app_url + - playground_ui + - base_url + - mcp_endpoint + - api_reference + - api_schema + - api_endpoint_default + - api_endpoint_batch + - api_endpoint_list_languages outputs: - app_url: + playground_ui: type: link title: "Playground UI URL" visible: true - - + base_url: + type: link + title: "Application Base URL" + visible: true + mcp_endpoint: + type: link + title: "MCP Endpoint" + visible: true + api_reference: + type: link + title: "API Reference" + visible: true + api_schema: + type: link + title: "API Schema" + visible: true + api_endpoint_default: + type: link + title: "API Endpoint - Translate" + visible: true + api_endpoint_batch: + type: link + title: "API Endpoint - Batch Translation Job" + visible: true + api_endpoint_list_languages: + type: link + title: "API Endpoint - Supported Languages" + visible: true diff --git a/ai-hub/ai-translation/policies/terraform/variables.tf b/ai-hub/ai-translation/policies/terraform/variables.tf index 6997cd26..522e1ca0 100644 --- a/ai-hub/ai-translation/policies/terraform/variables.tf +++ b/ai-hub/ai-translation/policies/terraform/variables.tf @@ -2,11 +2,6 @@ variable "tenancy_ocid" {} variable "compartment_ocid" {} variable "region" {} -variable "compartment_id" { - description = "The selected compartment, by default the compartment in which stack is created" - type = string -} - variable "availability_domain" { description = "Availabiliy domain" type = string @@ -17,6 +12,10 @@ variable "create_new_vcn" { type = bool default = true } +variable "vcn_compartment_id" { + description = "Compartment in which VCN, Subnets needs to be created or present" + type = string +} variable "existing_vcn_id" { type = string default = "" @@ -52,6 +51,10 @@ variable "identity_domain_id" { } #Vault Configuration to Store Identity App Client Secret +variable "vault_compartment_id" { + description = "Compartment in which Vault is present" + type = string +} variable "use_existing_vault" { type = bool description = "Use existing vault" @@ -77,8 +80,14 @@ variable "key_id" { # ------------------------- Environment variables required for Document Extraction Application ----------------------------- # # The following variables will be used by deployment. +variable "data_science_project_compartment_id" { + description = "Compartment in which Data Science Project is present" + type = string +} + variable "project_ocid" { - default = "ocid1.datascienceproject.oc1.iad.amaaaaaav66vvniaklsknycfb6fso64knuk36egpsg3j5vasn3sveiuvdmna" + type = string + description = "Data Science project in which resources needs to be created" } variable "log_group_ocid" { @@ -103,6 +112,10 @@ variable "ocpus" { } # The following variables are for job +variable "model_display_name" { + default = "AI Document Converter Model" +} + variable "job_display_name" { default = "AI Translation Job" } @@ -140,16 +153,15 @@ variable "model_url" { } variable "oci_cache_endpoint" { - # default = "" - default = "aaav66vvniax2viamc6jbwfeujiowpxnuu7kioiyfyqwgdptkwthq2q-p.redis.us-ashburn-1.oci.oraclecloud.com" + default = "" } variable "openai_api_key" { - default = "sk-123456789" + default = "API_KEY" } variable "translation_log_dir" { - default = "oci://a_bucket_for_qq@ociodscdev/data/translation/logs" + default = "" } variable "num_workers" { @@ -163,13 +175,13 @@ locals { app_subnet_id = (var.create_new_vcn ? oci_core_subnet.app_oci_core_subnet[0].id : var.existing_app_subnet_id) api_gw_subnet_id = (var.create_new_vcn ? oci_core_subnet.api_gw_oci_core_subnet[0].id : var.existing_api_gw_subnet_id) - image = "iad.ocir.io/ociodscdev/ai_translation:1.35" - digest = "sha256:9de28d33b7419b7f9ff42a6c2ad6792e904c3c815949f090e35e688cb23553fc" + image = "dsmc://ai-translation:0.1.0-dev.16" + digest = "sha256:124f2834142305c3f53f63d0c3f8aa071b9180d50f1c8c17fbf66937f183804c" job_desc = "Job for batch translation" job_entrypoint = ["python"] job_cmd = ["/opt/app/batch.py"] - model_id = "ocid1.datasciencemodel.oc1.iad.amaaaaaav66vvniazwx42xndxz3kfemfpwht3unc3ib33tscln462gmuwiyq" md_desc = "Deployment for AI translation Application" + model_desc = "Data Science Model for AI Translation Deployment" } diff --git a/ai-hub/ai-translation/policies/terraform/vault.tf b/ai-hub/ai-translation/policies/terraform/vault.tf index 992e3ece..32365b03 100644 --- a/ai-hub/ai-translation/policies/terraform/vault.tf +++ b/ai-hub/ai-translation/policies/terraform/vault.tf @@ -1,12 +1,12 @@ resource "oci_kms_vault" "app_vault" { - compartment_id = var.compartment_id + compartment_id = var.vault_compartment_id display_name = var.new_vault_display_name vault_type = "DEFAULT" count = var.use_existing_vault ? 0 : 1 } resource "oci_kms_key" "app_key" { - compartment_id = var.compartment_id + compartment_id = var.vault_compartment_id display_name = "${var.new_vault_display_name}-key" key_shape { algorithm = "AES" @@ -22,7 +22,7 @@ resource "oci_vault_secret" "idcs_app_client_secret" { oci_kms_key.app_key ] #Required - compartment_id = var.compartment_id + compartment_id = var.vault_compartment_id secret_content { #Required content_type = "BASE64" From ee118a38a6c8c765dabe5f06cf34dc7617a27d2f Mon Sep 17 00:00:00 2001 From: Vipul Date: Mon, 15 Sep 2025 12:26:01 -0700 Subject: [PATCH 4/6] update outputs --- ai-hub/ai-translation/policies/terraform/output.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ai-hub/ai-translation/policies/terraform/output.tf b/ai-hub/ai-translation/policies/terraform/output.tf index d8acde74..6d8a4741 100644 --- a/ai-hub/ai-translation/policies/terraform/output.tf +++ b/ai-hub/ai-translation/policies/terraform/output.tf @@ -10,12 +10,12 @@ output "mcp_endpoint" { output "playground_ui" { description = "Playground UI" - value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}playground/" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}ui/playground" } output "api_reference" { description = "API Reference" - value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}api/docs" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}ui/docs" } output "api_schema" { From c41db3068c2b8a282dd2d6096e46978e4a385def Mon Sep 17 00:00:00 2001 From: Vipul Date: Mon, 15 Sep 2025 15:12:54 -0700 Subject: [PATCH 5/6] stack update --- .../policies/terraform/container_instances.tf | 2 +- .../policies/terraform/datascience_job.tf | 2 +- .../policies/terraform/model.tf | 2 +- .../policies/terraform/model_deployment.tf | 4 +- .../policies/terraform/schema.yaml | 44 ++++--------------- .../policies/terraform/variables.tf | 10 +---- 6 files changed, 14 insertions(+), 50 deletions(-) diff --git a/ai-hub/ai-translation/policies/terraform/container_instances.tf b/ai-hub/ai-translation/policies/terraform/container_instances.tf index 9ea38d69..795c8812 100644 --- a/ai-hub/ai-translation/policies/terraform/container_instances.tf +++ b/ai-hub/ai-translation/policies/terraform/container_instances.tf @@ -16,7 +16,7 @@ resource "oci_container_instances_container_instance" "ai_container_instance" { NUM_WORKERS = var.num_workers TASK_STORE = "TMPDIR" LOG_DIR = var.translation_log_dir - PROJECT_COMPARTMENT_OCID = var.data_science_project_compartment_id + PROJECT_COMPARTMENT_OCID = var.compartment_ocid PROCESSING_JOB_OCID = oci_datascience_job.ai_job.id OCI_CACHE_ENDPOINT = var.oci_cache_endpoint BACKEND_MD_URL = oci_datascience_model_deployment.ai_deployment.model_deployment_url diff --git a/ai-hub/ai-translation/policies/terraform/datascience_job.tf b/ai-hub/ai-translation/policies/terraform/datascience_job.tf index 7dbef4f1..68dee886 100644 --- a/ai-hub/ai-translation/policies/terraform/datascience_job.tf +++ b/ai-hub/ai-translation/policies/terraform/datascience_job.tf @@ -3,7 +3,7 @@ resource "oci_datascience_job" "ai_job" { # Required display_name = var.job_display_name description = local.job_desc - compartment_id = var.data_science_project_compartment_id + compartment_id = var.compartment_ocid project_id = var.project_ocid job_configuration_details { diff --git a/ai-hub/ai-translation/policies/terraform/model.tf b/ai-hub/ai-translation/policies/terraform/model.tf index ba9f98ba..3d347632 100644 --- a/ai-hub/ai-translation/policies/terraform/model.tf +++ b/ai-hub/ai-translation/policies/terraform/model.tf @@ -27,7 +27,7 @@ data "archive_file" "model_zip" { # dummy Model catalog entry with artifact resource "oci_datascience_model" "ai_model" { - compartment_id = var.data_science_project_compartment_id + compartment_id = var.compartment_ocid project_id = var.project_ocid display_name = var.model_display_name description = local.model_desc diff --git a/ai-hub/ai-translation/policies/terraform/model_deployment.tf b/ai-hub/ai-translation/policies/terraform/model_deployment.tf index 74855fe9..43cb2fb1 100644 --- a/ai-hub/ai-translation/policies/terraform/model_deployment.tf +++ b/ai-hub/ai-translation/policies/terraform/model_deployment.tf @@ -3,7 +3,7 @@ resource "oci_datascience_model_deployment" "ai_deployment" { # Required display_name = var.deployment_display_name description = local.md_desc - compartment_id = var.data_science_project_compartment_id + compartment_id = var.compartment_ocid project_id = var.project_ocid model_deployment_configuration_details { @@ -42,7 +42,7 @@ resource "oci_datascience_model_deployment" "ai_deployment" { NUM_WORKERS = var.num_workers TASK_STORE = "TMPDIR", LOG_DIR = var.translation_log_dir - PROJECT_COMPARTMENT_OCID = var.data_science_project_compartment_id + PROJECT_COMPARTMENT_OCID = var.compartment_ocid PROCESSING_JOB_OCID = oci_datascience_job.ai_job.id OCI_CACHE_ENDPOINT = var.oci_cache_endpoint MODEL_DEPLOY_CUSTOM_ENDPOINTS = "[{\"endpointURI\": \"/api/languages\", \"httpMethods\": [\"GET\"]}, {\"endpointURI\": \"/api/batch\", \"httpMethods\": [\"POST\"]}, {\"endpointURI\": \"/api/task\", \"httpMethods\": [\"GET\"]}, {\"endpointURI\": \"/api/translate\", \"httpMethods\": [\"GET\", \"POST\"]}, {\"endpointURI\": \"/api/translate\", \"httpMethods\": [\"POST\"], \"streaming\": true}]" diff --git a/ai-hub/ai-translation/policies/terraform/schema.yaml b/ai-hub/ai-translation/policies/terraform/schema.yaml index 071d0629..4dd896d3 100644 --- a/ai-hub/ai-translation/policies/terraform/schema.yaml +++ b/ai-hub/ai-translation/policies/terraform/schema.yaml @@ -15,6 +15,7 @@ variableGroups: - region - vcn_display_name - deployment_type + - model_display_name - title: "General Configuration" variables: @@ -68,12 +69,6 @@ variableGroups: - container_shape - memory_in_gbs - ocpus - - title: "Application Configuration" - variables: - - genai_compartment_ocid - - data_science_project_compartment_id - - project_ocid - - deployment_display_name variables: # General @@ -228,13 +223,13 @@ variables: description: Compartment in which Identity Domain is present. default: compartment_ocid identity_domain_id: - type: oci:identity:domains:id - required: true - title: Identity domain - description: Identity Domain in which confidential integrated application needs to be created - visible: true - dependsOn: - compartmentId: ${identity_domain_compartment_id} + type: oci:identity:domains:id + required: true + title: Identity domain + description: Identity Domain in which confidential integrated application needs to be created + visible: true + dependsOn: + compartmentId: ${identity_domain_compartment_id} # Vault Configuration vault_compartment_id: type: oci:identity:compartment:id @@ -339,29 +334,6 @@ variables: default: 1 minimum: 1 maximum: 64 - #Application Configuration - data_science_project_compartment_id: - type: oci:identity:compartment:id - required: true - title: Data Science Project Compartment Id - description: Compartment in which Data Science Project is present. - default: compartment_ocid - project_ocid: - type: oci:ods:project:id - required: true - title: Select Data Science Project - dependsOn: - compartmentId: ${data_science_project_compartment_id} - log_group_ocid: - type: string - title: Log Group ocid - description: Log Group Ocid where logs will be stored - required: false - log_ocid: - type: string - title: Log ocid - description: Log ocid where where logs needs to be stored - required: false outputGroups: - title: "Application URLs" diff --git a/ai-hub/ai-translation/policies/terraform/variables.tf b/ai-hub/ai-translation/policies/terraform/variables.tf index 522e1ca0..edc56b1c 100644 --- a/ai-hub/ai-translation/policies/terraform/variables.tf +++ b/ai-hub/ai-translation/policies/terraform/variables.tf @@ -77,14 +77,6 @@ variable "key_id" { default = "none" } -# ------------------------- Environment variables required for Document Extraction Application ----------------------------- # - -# The following variables will be used by deployment. -variable "data_science_project_compartment_id" { - description = "Compartment in which Data Science Project is present" - type = string -} - variable "project_ocid" { type = string description = "Data Science project in which resources needs to be created" @@ -113,7 +105,7 @@ variable "ocpus" { # The following variables are for job variable "model_display_name" { - default = "AI Document Converter Model" + default = "AI Hub Empty Model" } variable "job_display_name" { From e14a2d884fcc8011b63694c1f289d9d7b0d6248b Mon Sep 17 00:00:00 2001 From: Vipul Date: Mon, 15 Sep 2025 15:13:41 -0700 Subject: [PATCH 6/6] add application info in stack --- .../policies/terraform/output.tf | 43 +++++++++++++++++-- .../policies/terraform/schema.yaml | 41 ++++++++++++++++-- 2 files changed, 77 insertions(+), 7 deletions(-) diff --git a/ai-hub/ai-document-converter/policies/terraform/output.tf b/ai-hub/ai-document-converter/policies/terraform/output.tf index d42e2eaa..04580834 100644 --- a/ai-hub/ai-document-converter/policies/terraform/output.tf +++ b/ai-hub/ai-document-converter/policies/terraform/output.tf @@ -1,4 +1,39 @@ -output "app_url" { - description = "Application URL" - value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}ui/" -} \ No newline at end of file +output "base_url" { + description = "Application Base URL" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}" +} + +output "mcp_endpoint" { + description = "MCP Endpoint" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}mcp" +} + +output "playground_ui" { + description = "Playground UI" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}ui/playground" +} + +output "api_reference" { + description = "API Reference" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}ui/docs" +} + +output "api_schema" { + description = "API Schema" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}api/openapi.json" +} + +output "api_endpoint_convert" { + description = "API Endpoint - Convert PDF from Object Storage to Markdown" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}api/convert" +} + +output "api_endpoint_convert_file" { + description = "API Endpoint - Convert PDF uploaded as file to Markdown" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}api/convert/file" +} + +output "api_endpoint_list_apis" { + description = "API Endpoint - Supported APIs for Document Conversion" + value = "${oci_apigateway_deployment.ai_application_apigateway_deployment.endpoint}api/list" +} diff --git a/ai-hub/ai-document-converter/policies/terraform/schema.yaml b/ai-hub/ai-document-converter/policies/terraform/schema.yaml index c396a60f..e83a5c1b 100644 --- a/ai-hub/ai-document-converter/policies/terraform/schema.yaml +++ b/ai-hub/ai-document-converter/policies/terraform/schema.yaml @@ -277,14 +277,49 @@ variables: outputGroups: - - title: "Application URL" + - title: "Application URLs" outputs: - - app_url + - playground_ui + - base_url + - mcp_endpoint + - api_reference + - api_schema + - api_endpoint_convert + - api_endpoint_convert_file + - api_endpoint_list_apis outputs: - app_url: + playground_ui: type: link title: "Playground UI URL" visible: true + base_url: + type: link + title: "Application Base URL" + visible: true + mcp_endpoint: + type: link + title: "MCP Endpoint" + visible: true + api_reference: + type: link + title: "API Reference" + visible: true + api_schema: + type: link + title: "API Schema" + visible: true + api_endpoint_convert: + type: link + title: "API Endpoint - Convert from OSS" + visible: true + api_endpoint_convert_file: + type: link + title: "API Endpoint - Convert from File" + visible: true + api_endpoint_list_apis: + type: link + title: "API Endpoint - Supported APIs" + visible: true