diff --git a/Server-Side Components/Script Includes/GetServiceDeskAgentHelpAIUtil/README.md b/Server-Side Components/Script Includes/GetServiceDeskAgentHelpAIUtil/README.md new file mode 100644 index 0000000000..6c41110b51 --- /dev/null +++ b/Server-Side Components/Script Includes/GetServiceDeskAgentHelpAIUtil/README.md @@ -0,0 +1,68 @@ +GetServiceDeskAgentHelpAIUtil +Overview +This is a client-callable Script Include designed for the ServiceNow platform that integrates with an external Databricks AI endpoint. Its purpose is to assist Service Desk agents by providing AI-generated responses to user queries, which can be used to populate incident information or assist in troubleshooting. +The script acts as a server-side proxy, handling the client-side request, invoking a Flow Designer Action to communicate with the Databricks service, and returning the AI's response to the client. +Features +AI-Powered Responses: Sends user search queries to a Databricks-powered Generative AI model to get intelligent answers. +Client-Callable: Can be invoked from client-side scripts (e.g., a UI Action or Client Script) using GlideAjax. +Flow Designer Integration: Uses a Flow Designer Action to execute the REST call to the Databricks endpoint, centralizing the external API logic. +Structured Output: Returns a JSON object containing the AI's response, model metadata, and a trace ID for debugging. +Prerequisites +ServiceNow Configuration +Flow Designer Action: A Flow Designer Action named global.genai_action must be created and configured to handle the REST call to the Databricks AI endpoint. This action must have: +An input named search_query (String). +An output named model_output (String). +Databricks Connection: The Flow Designer Action must be correctly configured with the necessary credentials to connect to the external Databricks API. +System Property: A system property named user.prompt is referenced in the script. It should be created and configured with the required prompt text for the AI. +How to use +1. Calling from a Client Script +You can use GlideAjax to call the getSearchResults function from a client-side script, such as a UI Action or a Catalog Client Script. +javascript +// Example client-side script using GlideAjax +var ga = new GlideAjax('GetServiceDeskAgentHelpAIUtil'); +ga.addParam('sysparm_name', 'getSearchResults'); +ga.addParam('sysparm_search_key', g_form.getValue('short_description')); // Pass the user's input +ga.getXML(getResponse); + +function getResponse(response) { + var answer = response.responseXML.documentElement.getAttribute("answer"); + if (answer) { + var result = JSON.parse(answer); + g_form.setValue('comments', result.modelResponse); // Set the AI response in a field + } +} +Use code with caution. + +2. Using from a Server Script +The functions can also be called directly from other server-side scripts (e.g., Business Rules). +javascript +// Example server-side script +var searchKey = 'What are the steps to reset my password?'; +var aiUtil = new GetServiceDeskAgentHelpAIUtil(); +var response = aiUtil.getSearchResults(searchKey); + +gs.info(response); +Use code with caution. + +Script details +getSearchResults() +This is the main function that coordinates the process. +Retrieves the search term from the client parameters. +Calls the getDataBricksModelResponse() function to get the AI-generated answer. +Constructs a JSON object with the AI's response and model information. +Returns the JSON object as a string. +getDataBricksModelResponse(search) +This function handles the integration with the Databricks AI. +Takes the search query as a parameter. +Executes the global.genai_action Flow Designer Action. +Parses the model_output from the Flow Action's outputs. +Extracts the AI's message content and a trace ID for debugging. +Returns a stringified JSON object containing the AI's response, date, and trace ID. +Includes a try/catch block to handle and log potential errors during the integration process. +Dependencies +Flow Designer Action: global.genai_action +System Property: user.prompt +Troubleshooting +Check the Flow Execution: If the AI response is not received, check the Flow Designer execution logs to ensure global.genai_action is running successfully and the REST call to Databricks is returning a valid response. +Review System Logs: Examine the System Logs (gs.info and gs.error messages) for debugging information related to the script's execution or potential errors from the Databricks API. +Verify Databricks Credentials: Ensure that the credentials and configuration within the Flow Designer action for connecting to Databricks are correct. diff --git a/Server-Side Components/Script Includes/GetServiceDeskAgentHelpAIUtil/script.js b/Server-Side Components/Script Includes/GetServiceDeskAgentHelpAIUtil/script.js new file mode 100644 index 0000000000..4bbc5f5800 --- /dev/null +++ b/Server-Side Components/Script Includes/GetServiceDeskAgentHelpAIUtil/script.js @@ -0,0 +1,110 @@ +var GetServiceDeskAgentHelpAIUtil = Class.create(); +GetServiceDeskAgentHelpAIUtil.prototype = Object.extendsObject(global.AbstractAjaxProcessor, { + + /** + * Main function that processes a search term from a client-side call, + * sends it to a Databricks-powered AI, and returns the response. + * This function is intended to assist Service Desk agents. + * + * @returns {string} A JSON string containing the AI's response, model details, and metrics. + */ + getSearchResults: function() { + // Defines the use case for logging and metric purposes. + var usecase = "ServiceDesk Helper"; + // Gets the current user's Sys ID, though it is not used in the current implementation. + var user = gs.getUserID(); + // Retrieves the search term passed from the client-side script. + var searchText = this.getParameter("sysparm_search_key"); + // Replaces double quotes with single quotes in the search text to prevent JSON parsing issues. + searchText = searchText.replaceAll('"', "'"); + + var searchObj = { + "searchValue": searchText.toString() + }; + + // Extracts the raw search value from the object. + var search = searchObj["searchValue"]; + + // This object is structured to create a prompt for another potential AI endpoint (possibly for a brief statement), + // but it is currently not used. + var brief_statement_payload = { + "messages": [{ + "role": "system", + "content": "You are an Expert ServiceNow bot that helps the users to create an incident" + }, + { + "role": "user", + "content": gs.getProperty('user.prompt') + search + } + ] + }; + + var databricks_model_response = {}; + // Calls the internal method to get the response from the Databricks model. + var response = this.getDataBricksModelResponse(search); + // UNCOMMENT THIS WHEN WE HAVE A PROPER SOLUTION FOR BRIEF RESPONSE GENERATION + // var brief_response = this.getBriefResponse(brief_statement_payload); + // The brief response is hardcoded to an empty JSON object + // Assigns the model response to the output object. + databricks_model_response.modelResponse = response; + // Assigns a hardcoded model ID. + databricks_model_response.model_id = "Databricks Runbook"; + + // Converts the final response object to a JSON string for client-side processing. + databricks_model_response = JSON.stringify(databricks_model_response); + // Logs the final JSON string for debugging purposes. + gs.info("Service Desk Helper Results: Testing value of the final databricks response being sent: " + databricks_model_response); + + // Returns the JSON string to the calling client script. + return databricks_model_response; + }, + + /** + * This function calls the Databricks endpoint via a Flow Designer action + * to generate an answer for the user's query. + * + * @param {string} search - The user's search query. + * @returns {string} A JSON string containing the AI's response, the current date, and a trace ID. + */ + getDataBricksModelResponse: function(search) { + try { + var inputs = {}; + // Maps the search query to the input expected by the flow action. + inputs['search_query'] = search; + + // Executes the specified Flow Designer action with the provided inputs. + // The action is run in the foreground, meaning the script will wait for a response. + var result = sn_fd.FlowAPI.getRunner().action('global.genai_action').inForeground().withInputs(inputs).run(); + // Retrieves the outputs from the completed flow action. + var outputs = result.getOutputs(); + + // Extracts the model output from the flow action outputs. + var model_output = outputs['model_output']; + // Attempts to parse and extract vector response data, though the variable is not used after this line. + var databricks_vector_response = JSON.parse(model_output).databricks_output.trace.data.spans; + + // Logs the raw response from the Databricks model for debugging. + gs.info("Helper Results: Databricks flow action response: " + JSON.stringify(model_output)); + + var current_date = new GlideDateTime(); + var output = {}; + // Parses the model output to extract the AI's content. + output.response = JSON.parse(model_output).choices[0].message.content; + // Adds the current date to the output object. + output.date = current_date.getDisplayValue(); + // Logs the trace ID for tracking purposes. + gs.info("Helper Results: GEN AI flow action TraceID value: " + JSON.parse(model_output).id); + // Adds the trace ID to the output object. + output.traceID = JSON.parse(model_output).id; + // Returns the constructed output object as a JSON string. + return JSON.stringify(output); + + } catch (ex) { + // Catches any exceptions during the flow execution and logs an error. + var message = ex.getMessage(); + gs.error(message); + } + }, + + type: 'GetServiceDeskAgentHelpAIUtil' +});