Salesforce Integration With Gemini Text Generation

 Salesforce Integration With Gemini Text Generation

In today's fast-paced world, integrating AI into business processes is no longer a luxury but a necessity. Salesforce, a leading CRM platform, provides robust tools to connect with external services. Gemini, Google's powerful AI model, offers exceptional text generation capabilities. This blog post will guide you through connecting Salesforce with Gemini's text generation API, enabling you to leverage AI within your Salesforce environment.

Experience the Salesforce Gemini Integration in Action


1. Google Cloud : Creating an API Key

All locks open with a key... in the Google world, the access to API's is unlocked with an API key. 
Go to your Google Cloud console and create a new project and an API key

2. Setting the Stage: Authentication with Named Credentials and External Credentials

To securely connect Salesforce with external services like Gemini, we'll use Named Credentials and External Credentials. This method allows Salesforce to handle authentication details without exposing them in your code.

2.1. Create a Named Credential

A Named Credential specifies the URL of the callout endpoint and its authentication parameters.

Navigate to Setup > Security > Named Credentials

Click New

Label: Gemini AI Search

Name: Gemini_AI_Search

URL: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent

Enabled for Callouts : true

Under Callout Options

Generate Authorization Header : true

Click Save.

2.2. Create an External Credential

An External Credential defines the authentication protocol and permissions used for external access. Here, we'll store our Gemini API key.

From Named Credential navigate to External Credentials tab.

Click New

Label: Gemini AI Search

Name: Gemini_AI_Search

Authentication Protocol: No Authentication (We'll handle the API key through the External Credential)

Click Save.

2.3. Create a Principal

A Principal links the External Credential to a Permission Set, granting specific users access.

On the Gemini_AI_Search detail page, go to the Principals related list.

Click New.

Name: Full_Access

Click Save.

Now, you need to assign this Principal to a Permission Set. Create a new Permission Set (e.g., Gemini_API_Access) and add the Gemini_Principal to it. Assign this Permission Set to users who need access to the Gemini API.


3. The Apex Class : Interacting with Gemini

3.1 GeminiAISearch.cls

Now, let's create an Apex class that will make the callout to the Gemini API.

public with sharing class GeminiAISearch {
    public GeminiAISearch() {

    }

    @AuraEnabled(cacheable=false)
    public static String getDetails(String userQuery) {
        Http httpCall = new Http();
        
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:Gemini_AI_Search');
        req.setHeader('X-goog-api-key', Label.Gemini_AI_Search_API_Key);
        req.setMethod('POST');
        req.setTimeout(120000);
        String strBody = '{"contents": [{"parts": [{"text": "'+userQuery+'"}]}]}';
        req.setBody(strBody);
        
        HttpResponse resp = httpCall.send(req);
        return resp.getBody();
    }
}

4. The LWC Component: User Interface for Interaction

4.1 GeminiAISearch.html

<template>
    <lightning-card title="Gemini AI Search Demo" icon-name="custom:custom14">
        <div class="slds-m-around_medium">
            <!-- Input Textarea -->
            <lightning-textarea
                label="Enter Your Search Term"
                value={userQuery}
                onchange={handleQueryChange}
                placeholder="Type your query here..."
            ></lightning-textarea>

            <!-- Submit Button -->
            <div class="slds-m-top_medium">
                <lightning-button
                    label="Fetch Details From Gemini"
                    onclick={handleButtonClick}
                    variant="brand"
                    disabled={isButtonDisabled}
                ></lightning-button>
            </div>

            <!-- Loading Spinner -->
            <template if:true={isLoading}>
                <div class="slds-m-top_medium">
                    <lightning-spinner alternative-text="Connecting with Gemini..." size="medium"></lightning-spinner>
                    <div class="slds-text-align_center slds-m-top_x-small">Fetching details for your query...</div>
                </div>
            </template>

            <!-- Result Textarea (Read-only) -->
            <template if:true={result}>
                <div class="slds-m-top_large">
                    <lightning-textarea
                        class="custom-height"
                        label="Result"
                        value={result}
                        lwc:ref="resultSection"
                        readonly
                    ></lightning-textarea>
                </div>
            </template>
        </div>
    </lightning-card>
</template>

4.2 GeminiAISearch.js

import { LightningElement, track } from 'lwc';
import invokeApex from '@salesforce/apex/GeminiAISearch.getDetails';

export default class GeminiAISearch extends LightningElement {
    @track userQuery = '';
    @track result = '';
    @track isLoading = false;

    // Handles the change event from the textarea
    handleQueryChange(event) {
        this.userQuery = event.target.value;
    }

    // Handles the button click to call the Apex class
    handleButtonClick() {
        if (!this.userQuery) {
            return;
        }

        this.isLoading = true; // Show the loading message
        this.result = ''; // Clear previous results
        invokeApex({ userQuery: this.userQuery })
            .then(data => {
                this.isLoading = false; // Hide the loading message
                this.parseJSONResponse(this.result);
            })
            .catch(error => {
                this.isLoading = false; // Hide the loading message on error
                this.result = 'An error occurred. Please try again.';
            });
    }

    parseJSONResponse(resp){
        let parsedValue = JSON.parse(resp);
        this.result = parsedValue.candidates[0].content.parts[0].text;
    }

    // A getter to disable the button when the query is empty or a process is running
    get isButtonDisabled() {
        return !this.userQuery || this.isLoading;
    }
}

4.3 GeminiAISearch.css

    .custom-height {
        --sds-c-textarea-sizing-min-height: 200px; /* Adjust the pixel value as needed */
    }

4.4 GeminiAISearch.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>64.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
        <target>lightningCommunity__Page</target>
    </targets>
</LightningComponentBundle>

5. Deploying and Using the Component

Deploy the Apex Class and LWC component to your Salesforce Org.

Add the LWC to a Lightning Page (or Public Community page):

Navigate to an App Page, Record Page, or Home Page where you want to display the component.

Click the Gear Icon (Setup) > Edit Page.

Drag the gemini_ai_search component from the Custom Components section onto your page.

Save and Activate the page.

Now, users with the assigned Permission Set can access the component, enter a prompt, and see the text generated by Gemini!

6. Get the Code

You can find the complete code for this example in the following GitHub repository:


Conclusion

By following these steps, you've successfully integrated Salesforce with Gemini's powerful text generation capabilities. This opens up a world of possibilities for automating content creation, enhancing customer service with AI-powered responses, summarizing data, and much more, all directly within your Salesforce environment.

Happy AI Integrating!

Vivian Charlie

References


Comments