Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions ai/custom-func-ai-agent/AiVertex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
Copyright 2025 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

const LOCATION = PropertiesService.getScriptProperties().getProperty('LOCATION');
const GEMINI_MODEL_ID = PropertiesService.getScriptProperties().getProperty('GEMINI_MODEL_ID');
const REASONING_ENGINE_ID = PropertiesService.getScriptProperties().getProperty('REASONING_ENGINE_ID');
const SERVICE_ACCOUNT_KEY = PropertiesService.getScriptProperties().getProperty('SERVICE_ACCOUNT_KEY');

const credentials = credentialsForVertexAI();

/**
* @param {string} statement The statement to fact-check.
*/
function requestLlmAuditorAdkAiAgent(statement) {
return UrlFetchApp.fetch(
`https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${credentials.projectId}/locations/${LOCATION}/reasoningEngines/${REASONING_ENGINE_ID}:streamQuery?alt=sse`,
{
method: 'post',
headers: { 'Authorization': `Bearer ${credentials.accessToken}` },
contentType: 'application/json',
muteHttpExceptions: true,
payload: JSON.stringify({
"class_method": "async_stream_query",
"input": {
"user_id": "google_sheets_custom_function_fact_check",
"message": statement,
}
})
}
).getContentText();
}

/**
* @param {string} prompt The Gemini prompt to use.
*/
function requestOutputFormatting(prompt) {
const response = UrlFetchApp.fetch(
`https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${credentials.projectId}/locations/${LOCATION}/publishers/google/models/${GEMINI_MODEL_ID}:generateContent`,
{
method: 'post',
headers: { 'Authorization': `Bearer ${credentials.accessToken}` },
contentType: 'application/json',
muteHttpExceptions: true,
payload: JSON.stringify({
"contents": [{
"role": "user",
"parts": [{ "text": prompt }]
}],
"generationConfig": { "temperature": 0.1, "maxOutputTokens": 2048 },
"safetySettings": [
{
"category": "HARM_CATEGORY_HARASSMENT",
"threshold": "BLOCK_NONE"
},
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"threshold": "BLOCK_NONE"
},
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"threshold": "BLOCK_NONE"
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"threshold": "BLOCK_NONE"
}
]
})
}
);
return JSON.parse(response).candidates[0].content.parts[0].text
}

/**
* Gets credentials required to call Vertex API using a Service Account.
* Requires use of Service Account Key stored with project.
*
* @return {!Object} Containing the Google Cloud project ID and the access token.
*/
function credentialsForVertexAI() {
const credentials = SERVICE_ACCOUNT_KEY;
if (!credentials) {
throw new Error("service_account_key script property must be set.");
}

const parsedCredentials = JSON.parse(credentials);

const service = OAuth2.createService("Vertex")
.setTokenUrl('https://oauth2.googleapis.com/token')
.setPrivateKey(parsedCredentials['private_key'])
.setIssuer(parsedCredentials['client_email'])
.setPropertyStore(PropertiesService.getScriptProperties())
.setScope("https://www.googleapis.com/auth/cloud-platform");
return {
projectId: parsedCredentials['project_id'],
accessToken: service.getAccessToken(),
}
}
36 changes: 36 additions & 0 deletions ai/custom-func-ai-agent/Code.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
Copyright 2025 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/**
* Passes a statement to fact-check and, optionally, output formatting instructions.
*
* @param {string} statement The statement to fact-check as a string or single cell
* reference (data ranges are not supported).
* @param {string} outputFormat The instructions as a string or single cell reference
* (data ranges are not supported).
*
* @return The generated and formatted verdict
* @customfunction
*/
function FACT_CHECK(statement, outputFormat) {
if (!outputFormat || outputFormat == "") {
outputFormat = 'Summarize it. Only keep the verdict result and main arguments. '
+ 'Do not reiterate the fact being checked. Remove all markdown. '
+ 'State the verdit result in a first paragraph in a few words and the rest of the summary in a second paragraph.';
}

return requestOutputFormatting(`Here is a fact checking result: ${requestLlmAuditorAdkAiAgent(statement)}.\n\n${outputFormat}`);
}
38 changes: 38 additions & 0 deletions ai/custom-func-ai-agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Google Sheets Custom Function relying on ADK AI Agent and Gemini model

A [Vertex AI](https://cloud.google.com/vertex-ai) agent-powered **fact checker** custom function for Google Sheets to be used as a bound Apps Script project.

![](./images/showcase.png)

## Overview

The **Google Sheets custom function** named `FACT_CHECK` integrates the sophisticated, multi-tool, multi-step reasoning capabilities of a **Vertex AI Agent Engine (ADK Agent)** directly into your Google Sheets spreadsheets.

It operates as an end-to-end solution. It analyzes a statement, grounds its response using the latest web information, and returns the result in the format you need:

* Usage: `=FACT_CHECK("Your statement here")` for a concise and summarized output. `=FACT_CHECK("Your statement here", "Your output formatting instructions here")` for a specific output format.
* Reasoning: [**LLM Auditor ADK AI Agent (Python sample)**](https://github.com/google/adk-samples/tree/main/python/agents/llm-auditor).
* Output formatting: [**Gemini model**](https://cloud.google.com/vertex-ai/generative-ai/docs/models).

## Prerequisites

* Google Cloud Project with billing enabled.

## Set up your environment

1. Configure the Google Cloud project
1. Enable the Vertex AI API
1. Create a Service Account and grant the role `Vertex AI User`
1. Create a private key with type JSON. This will download the JSON file.
1. Setup, install, and deploy the LLM Auditor ADK AI Agent sample
1. Use Vertex AI
1. Use the same Google Cloud project
1. Use the location `us-central1`
1. Use the Vertex AI Agent Engine
1. Open an Apps Script project bound to a Google Sheets spreadsheet
1. Add a Script Property. Enter `LOCATION` as the property name and `us-central1` as the value.
1. Add a Script Property. Enter `GEMINI_MODEL_ID` as the property name and `gemini-2.5-flash-lite` as the value.
1. Add a Script Property. Enter `REASONING_ENGINE_ID` as the property name and the ID of the deployed LLM Auditor ADK AI Agent as the value.
1. Add a Script Property. Enter `SERVICE_ACCOUNT_KEY` as the property name and paste the JSON key from the service account as the value.
1. Add OAuth2 v43 Apps Script Library using the ID `1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF`
1. Set the script files `Code.gs` and `AiVertex.gs` in the Apps Script project with the JS file contents in this project
12 changes: 12 additions & 0 deletions ai/custom-func-ai-agent/appsscript.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"timeZone": "America/Los_Angeles",
"dependencies": {
"libraries": [{
"userSymbol": "OAuth2",
"libraryId": "1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF",
"version": "43"
}]
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8"
}
Binary file added ai/custom-func-ai-agent/images/showcase.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading