Unlock the Power of Vertex AI for ColdFusion Developers

Aaron Rouse
9 min readFeb 26, 2024

--

Unlock the Power of Vertex AI for ColdFusion Developers

Introduction

Have you ever faced a feature in your Adobe ColdFusion application that you wished was a bit more…intelligent? Frustrated by manual image tagging? Need to make better data-driven predictions? Or perhaps you want to build a conversational chatbot that truly understands your users? Or perhaps wanted to add a touch of creative text generation? Google Cloud’s Vertex AI provides the solutions to elevate your ColdFusion applications with sophisticated AI capabilities.

In this blog, we’ll focus on tapping into the power of AI-fueled language generation using Vertex AI and Gemini. I’ll walk you through setting up a service account, handling authentication, and the core of it all. Then how to send prompts and receive tailored, creative text responses generated by cutting-edge AI models. But that’s just the beginning. Let’s imagine the possibilities:

  • Dynamic Content Generation: Effortlessly create engaging marketing copy, email drafts, or even short social media posts tailored to specific topics or audiences.
  • Enhanced User Interactions: Build chatbots and virtual assistants that feel more natural and responsive, providing tailored information and support powered by AI-driven language understanding.

If you’re eager to inject a dose of AI-powered text creativity into your ColdFusion applications, you’re in the right place! Let’s dive into harnessing the capabilities of Vertex AI.

Step 1: Enable the Vertex AI API

  1. Visit the Cloud Console.
  2. Select your Project from the dropdown menu in the top-left corner.

3. Click on the Hamburger icon in the top left then “”APIs & Services” and then “Library”.

4. Search for “Vertex AI API” and click the “Enable” button.

Step 2: Test a Prompt in Vertex AI

  1. Type “Vertex AI” into the search box at the top of the Console and click on “Vertex AI” under the “Products & Pages”

2. If displayed click on “Enable All Recommended APIs” button

3. In the left hand menu under “Vertex AI Studio” click on “Language”

4. Under “Create a new prompt” click on “Text Prompt” button

5. Type into the Prompt box a sample Prompt that you would like to test with (e.g., Write me a poem about beer) and then click on the Submit button. Within the Response section you will see what was generated for your Prompt.

6. In the upper right of the Console click on the “<> Get Code” button and then the “Curl” button. This will give you the value for your request.json file that will be needed later as well as the values needed for the API call that will be used with that.

Create request.json file

Copy the value for the request.json file out of the Curl command and write to a file named request.json then upload that file into the web root on your ColdFusion server. This file could be replaced via code creation within your application. The contents of your file will look similar to following, you do not need to include the safety settings section if made no changes to them:

{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Write me a poem about beer"
}
]
}
],
"generation_config": {
"maxOutputTokens": 2048,
"temperature": 0.9,
"topP": 1
}
}

If instead using code within your application to set the request json value you would do something similar to this:

<cfscript>
REQUEST_JSON = '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Write me a poem about IPA beer"
}
]
}
],
"generation_config": {
"maxOutputTokens": 2048,
"temperature": 0.4,
"topP": 1,
"topK": 32
}
}';
</cfscript>

Step 3: Create a Service Account

  1. Click on the Hamburger icon in the top left then “IAM & Admin” and then “Service Accounts”

2. Click on “Create Service Account” button

3. Enter a unique name for your service account (e.g., “coldfusion-vertex-ai-sa”)

4. Click “Create and Continue” button

5. Select a role that grants your service account the necessary permissions for Vertex AI (e.g., “Vertex AI User”).

6. Click “Done” to create the Service Account

Step 4: Generate a Service Account Key

  1. Click on the name of the Service Account you just created.
  2. Click on the “Keys” tab
  3. Click on “Add Key” button and then “Create new key”
  4. Select “JSON” for the Key type and then click the “Create” button
  5. Save the created JSON file that contains the key to a secure location.

Step 5: Service Account Key with ColdFusion

To interact with Vertex AI from ColdFusion, you’ll need to handle the JSON file containing your service account key with care. Here’s a breakdown of best practices:

  1. Secure Location: Upload the JSON key file to a directory on your ColdFusion server that is not publicly accessible via the web. Restrict file system permissions so only the ColdFusion process can access it.
  2. Secrets Management (Production): For enhanced security in production environments, consider using a secrets manager. These services provide secure storage and access control for sensitive data like API keys.
  3. File Path Reference: Take note of the exact file path to your key file. For this example, let’s assume it’s named sa-key.json and located at /opt/coldfusion/cfusion/sa-key.json

Step 6: ColdFusion Code Examples

To make calls to the Vertex AI API, your ColdFusion code needs to authenticate with Google Cloud. This ensures that Google knows the requests are coming from an authorized source and allows your application to tap into Vertex AI’s powerful capabilities. Remember the “gcloud auth login” step from Step 2? That command provided a similar form of authentication when we worked directly from the command line.

Now, let’s dive into two ways to handle this authentication directly within your ColdFusion environment. Since ColdFusion runs on top of Java, we can take advantage of Java’s established integration with Google Cloud services for secure and streamlined authentication.

Oauth

One straightforward way to manage authentication in your ColdFusion application is using Google’s OAuth client library. OAuth provides a secure, standard way for applications to interact with each other without you having to manually manage and expose user passwords. With a few simple setup steps and some additions to your ColdFusion code, you’ll have seamless authentication to the power of Vertex AI. Here’s what you need to do, followed by a clear code example:

  1. Download the JAR:

2. Place the JAR:

  • Move the downloaded JAR file to /opt/coldfusion/cfusion/wwwroot/WEB-INF/lib.

3. Restart ColdFusion:

  • Restart your ColdFusion server to ensure it recognizes the new library.

Code Explanation

To use this library, create a CFM file within your webroot. This file needs access to both your request.json (for your API request data) and your sa-key.json (for authentication). Replace the following placeholders in the code with your actual values: API_ENDPOINT, PROJECT_ID, MODEL_ID, and LOCATION_ID.

The code will look like this:

<cfscript>
API_ENDPOINT = "us-central1-aiplatform.googleapis.com";
PROJECT_ID = "coldfusion-on-cloudrun";
MODEL_ID = "gemini-pro";
LOCATION_ID = "us-central1";
REQUEST_JSON = FileRead(ExpandPath("./request.json"));
strDisplay = "";

// Authenticate via OAuth
OAuth2Googletoken = CreateObject("java", "com.google.auth.oauth2.GoogleCredentials")
.fromStream(createobject("java", "java.io.FileInputStream").init(ExpandPath("../sa-key.json")))
.createScoped(JavaCast("string[]", ["https://www.googleapis.com/auth/cloud-platform"]))
.refreshAccessToken()
.getTokenValue();

// HTTP Request to Vertex AI
// Build the URL with variables
TheURL = "https://#API_ENDPOINT#/v1/projects/#PROJECT_ID#/locations/#LOCATION_ID#/publishers/google/models/#MODEL_ID#:streamGenerateContent";
// Create the HTTP request object
httpService = new http(method="POST", url=TheURL);

// Add headers
httpService.addParam(type="header", name="Authorization", value="Bearer #OAuth2Googletoken#");
httpService.addParam(type="header", name="Content-Type", value="application/json");

// Set the request body
httpService.addParam(type="body", value=REQUEST_JSON);
// Send the Request and Get Response
apiResponse = httpService.send().getPrefix();
// Output the results from Vertex AI
if(StructKeyExists(apiResponse, "FileContent") AND IsJSON(apiResponse.FileContent)) {
// Deserialize JSON Response
myResult = DeserializeJSON(apiResponse.FileContent);
// Find all of the keys with the output text
myResult = StructFindKey({ myResult }, "text", "All");
// Build the string to display
myResult.each((strText, index, array) => {
strDisplay &= strText["value"];
});
// Output the built string
WriteOutput(ParagraphFormat(strDisplay));
}
</cfscript>

JWT

If working in an environment where not allowed to add the Oauth library then a different way would be to create a JWT via Java and use that with your call to the API. This is constructed using the Service Account’s credentials that are pulled from the sa-key.json file and allows for authentication for the API. The JWT is made of of three parts:

  • JWT Header: The header contains information about the algorithm used to sign the JWT (alg) and the type of JWT (typ). In this case, the header is set to use the RS256 algorithm and the JWT type is set to JWT.
  • JWT Claims: The JWT claims contain information about the subject of the JWT (iss), the scope of the JWT (scope), the audience of the JWT (aud), the time the JWT was issued (IAT), and the time the JWT expires (exp). In this case, the subject is set to the Service Account’s client email, the scope is set to the Google Cloud API, the audience is set to the Google OAuth2 token endpoint, the issued at time is set to the current time, and the expiration is set to one hour from the issued at time.
  • JWT Signature: The JWT signature is a cryptographic hash of the header and claims, signed using the Service Acocunt’s private key. The signature is used to verify that the JWT has not been tampered with.

The three parts are concatenated together using periods, and the resulting string is the JWT.

<cfscript>
API_ENDPOINT = "us-central1-aiplatform.googleapis.com";
PROJECT_ID = "coldfusion-on-cloudrun";
MODEL_ID = "gemini-pro";
LOCATION_ID = "us-central1";
REQUEST_JSON = FileRead(ExpandPath("./request.json"));
strDisplay = "";

// JWT
// Load Service Account Credentials
SERVICE_JSON = DeserializeJSON(FileRead(ExpandPath("../sa-key.json")));
CLIENT_EMAIL = SERVICE_JSON.CLIENT_EMAIL;
PRIVATE_KEY = SERVICE_JSON.PRIVATE_KEY;
// Construct JWT Header
jwt_header = {
'alg': 'RS256',
'typ': 'JWT'
};
jwt_header = serializeJSON(jwt_header);
jwt_header = toBase64(jwt_header, "utf-8");
// Construct JWT Claims
iat = dateDiff("s", CreateDate(1970,1,1), now());
exp = iat + 3600; // Expire in 1 hour
jwt_claim = {
'iss': CLIENT_EMAIL,
'scope': 'https://www.googleapis.com/auth/cloud-platform',
'aud': 'https://www.googleapis.com/oauth2/v4/token',
'iat': iat,
'exp': exp
};
jwt_claim = serializeJSON(jwt_claim);
jwt_claim = toBase64(jwt_claim, "utf-8");
// Sign JWT
keyText = reReplace(private_key, "-----(BEGIN|END)[^\r\n]+", "", "all");
keyText = trim(keyText);

privateKeySpec = createObject("java", "java.security.spec.PKCS8EncodedKeySpec").init(binaryDecode(keyText, "base64"));

privateKey = createObject("java", "java.security.KeyFactory").getInstance("RSA").generatePrivate(privateKeySpec);

signer = createObject("java", "java.security.Signature").getInstance("SHA256withRSA");

signer.initSign(privateKey);
signer.update(charsetDecode(jwt_header & "." & jwt_claim, "utf-8"));
signedBytes = signer.sign();
jwt_signature = toBase64(signedBytes, "utf-8");
// Assemble JWT
jwt = jwt_header & "." & jwt_claim & "." & jwt_signature;
// HTTP Request to authenticate
// Create the HTTP object
httpService = new http(method="POST", url="https://www.googleapis.com/oauth2/v4/token");
// Add the form fields
httpService.addParam(type="formField", name="grant_type", value="urn:ietf:params:oauth:grant-type:jwt-bearer");
httpService.addParam(type="formField", name="assertion", value=jwt);
// Send the Request and Get Response
result = httpService.send().getPrefix();
// Deserialize JSON Response
myToken = deserializeJSON(result.filecontent);
// HTTP Request to Vertex AI
// Build the URL with variables
TheURL = "https://#API_ENDPOINT#/v1/projects/#PROJECT_ID#/locations/#LOCATION_ID#/publishers/google/models/#MODEL_ID#:streamGenerateContent";
// Create the HTTP object
httpService = new http(method="POST", url=TheURL);
// Add Headers
httpService.addParam(type="header", name="Authorization", value="Bearer #myToken.access_token#");
httpService.addParam(type="header", name="Content-Type", value="application/json");
// Add the Request Body
httpService.addParam(type="body", value=REQUEST_JSON);
// Send the Request and Get Response
apiResponse = httpService.send().getPrefix();
// Output the results from Vertex AI
if(StructKeyExists(apiResponse, "FileContent") AND IsJSON(apiResponse.FileContent)) {
// Deserialize JSON Response
myResult = DeserializeJSON(apiResponse.FileContent);

// Find all of the keys with the output text
myResult = StructFindKey({ myResult }, "text", "All");

// Build the string to display
myResult.each((strText, index, array) => {
strDisplay &= strText["value"];
});

WriteOutput(ParagraphFormat(strDisplay));
}
</cfscript>

Conclusion

By following these steps, you’ve successfully bridged the gap between your ColdFusion applications and the remarkable world of Vertex AI. Just as we discussed in the beginning, this unlocks endless possibilities for intelligent features. Need help with image tagging? Want to generate tailored, engaging text with ease? Looking to build truly responsive chatbots? These are just the tip of the iceberg!

Remember to prioritize security by managing your Service Account key wisely and using appropriate permissions. With this strong foundation, the power of AI is at your fingertips to elevate your ColdFusion applications.

Now, the real fun begins. Experiment, explore, and see how Vertex AI can transform what you build with ColdFusion!

--

--

Aaron Rouse

Just your everyday IT Nerd and Gearhead. Professional amateur virtual race car driver at night and during the day a Google Cloud Principal Architect