Vertex: Add Vertex AI-specific safety setting (#4770) Closes #4455

1baaa26729b173afde7df3ca844a2d7add939fb6

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
3 files changed, +33 -8Ignore whitespace
src/constants.js+23 -0
@@ -161,6 +161,29 @@ export const GEMINI_SAFETY = [
161 },161 },
162];162];
163163
164export const VERTEX_SAFETY = [
165 {
166 category: 'HARM_CATEGORY_IMAGE_HATE',
167 threshold: 'OFF',
168 },
169 {
170 category: 'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT',
171 threshold: 'OFF',
172 },
173 {
174 category: 'HARM_CATEGORY_IMAGE_HARASSMENT',
175 threshold: 'OFF',
176 },
177 {
178 category: 'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT',
179 threshold: 'OFF',
180 },
181 {
182 category: 'HARM_CATEGORY_JAILBREAK',
183 threshold: 'OFF',
184 },
185];
186
164export const CHAT_COMPLETION_SOURCES = {187export const CHAT_COMPLETION_SOURCES = {
165 OPENAI: 'openai',188 OPENAI: 'openai',
166 CLAUDE: 'claude',189 CLAUDE: 'claude',
src/endpoints/backends/chat-completions.js+2 -1
@@ -12,6 +12,7 @@ import {
12 OPENAI_REASONING_EFFORT_MAP,12 OPENAI_REASONING_EFFORT_MAP,
13 OPENAI_REASONING_EFFORT_MODELS,13 OPENAI_REASONING_EFFORT_MODELS,
14 OPENROUTER_HEADERS,14 OPENROUTER_HEADERS,
15 VERTEX_SAFETY,
15} from '../../constants.js';16} from '../../constants.js';
16import {17import {
17 forwardFetchResponse,18 forwardFetchResponse,
@@ -405,7 +406,7 @@ async function sendMakerSuiteRequest(request, response) {
405406
406 const tools = [];407 const tools = [];
407 const prompt = convertGooglePrompt(request.body.messages, model, useSystemPrompt, getPromptNames(request));408 const prompt = convertGooglePrompt(request.body.messages, model, useSystemPrompt, getPromptNames(request));
408 let safetySettings = GEMINI_SAFETY;409 const safetySettings = [...GEMINI_SAFETY, ...(useVertexAi ? VERTEX_SAFETY : [])];
409410
410 if (enableWebSearch && !enableImageModality && !isGemma && !isLearnLM && !noSearchModels.includes(model)) {411 if (enableWebSearch && !enableImageModality && !isGemma && !isLearnLM && !noSearchModels.includes(model)) {
411 tools.push({ google_search: {} });412 tools.push({ google_search: {} });
src/endpoints/google.js+8 -7
@@ -8,7 +8,7 @@ import urlJoin from 'url-join';
8import lodash from 'lodash';8import lodash from 'lodash';
99
10import { readSecret, SECRET_KEYS } from './secrets.js';10import { readSecret, SECRET_KEYS } from './secrets.js';
11import { GEMINI_SAFETY } from '../constants.js';11import { GEMINI_SAFETY, VERTEX_SAFETY } from '../constants.js';
12import { delay, getConfigValue, trimTrailingSlash } from '../util.js';12import { delay, getConfigValue, trimTrailingSlash } from '../util.js';
1313
14const API_MAKERSUITE = 'https://generativelanguage.googleapis.com';14const API_MAKERSUITE = 'https://generativelanguage.googleapis.com';
@@ -159,12 +159,13 @@ export function getProjectIdFromServiceAccount(serviceAccount) {
159 * @param {express.Request} request Express request object159 * @param {express.Request} request Express request object
160 * @param {string} model Model name to use160 * @param {string} model Model name to use
161 * @param {string} endpoint API endpoint (default: 'generateContent')161 * @param {string} endpoint API endpoint (default: 'generateContent')
162 * @returns {Promise<{url: string, headers: object, apiName: string, baseUrl: string}>} URL, headers, and API name162 * @returns {Promise<{url: string, headers: object, apiName: string, baseUrl: string, safetySettings: object[]}>} URL, headers, and API name
163 */163 */
164export async function getGoogleApiConfig(request, model, endpoint = 'generateContent') {164export async function getGoogleApiConfig(request, model, endpoint = 'generateContent') {
165 const useVertexAi = request.body.api === 'vertexai';165 const useVertexAi = request.body.api === 'vertexai';
166 const region = request.body.vertexai_region || 'us-central1';166 const region = request.body.vertexai_region || 'us-central1';
167 const apiName = useVertexAi ? 'Google Vertex AI' : 'Google AI Studio';167 const apiName = useVertexAi ? 'Google Vertex AI' : 'Google AI Studio';
168 const safetySettings = [...GEMINI_SAFETY, ...(useVertexAi ? VERTEX_SAFETY : [])];
168169
169 let url;170 let url;
170 let baseUrl;171 let baseUrl;
@@ -225,7 +226,7 @@ export async function getGoogleApiConfig(request, model, endpoint = 'generateCon
225 headers['x-goog-api-key'] = apiKey;226 headers['x-goog-api-key'] = apiKey;
226 }227 }
227228
228 return { url, headers, apiName, baseUrl };229 return { url, headers, apiName, baseUrl, safetySettings };
229}230}
230231
231export const router = express.Router();232export const router = express.Router();
@@ -235,7 +236,7 @@ router.post('/caption-image', async (request, response) => {
235 const mimeType = request.body.image.split(';')[0].split(':')[1];236 const mimeType = request.body.image.split(';')[0].split(':')[1];
236 const base64Data = request.body.image.split(',')[1];237 const base64Data = request.body.image.split(',')[1];
237 const model = request.body.model || 'gemini-2.0-flash';238 const model = request.body.model || 'gemini-2.0-flash';
238 const { url, headers, apiName } = await getGoogleApiConfig(request, model);239 const { url, headers, apiName, safetySettings } = await getGoogleApiConfig(request, model);
239240
240 const body = {241 const body = {
241 contents: [{242 contents: [{
@@ -249,7 +250,7 @@ router.post('/caption-image', async (request, response) => {
249 },250 },
250 }],251 }],
251 }],252 }],
252 safetySettings: GEMINI_SAFETY,253 safetySettings: safetySettings,
253 };254 };
254255
255 console.debug(`${apiName} captioning request`, model, body);256 console.debug(`${apiName} captioning request`, model, body);
@@ -355,7 +356,7 @@ router.post('/list-native-voices', async (_, response) => {
355router.post('/generate-native-tts', async (request, response) => {356router.post('/generate-native-tts', async (request, response) => {
356 try {357 try {
357 const { text, voice, model } = request.body;358 const { text, voice, model } = request.body;
358 const { url, headers, apiName } = await getGoogleApiConfig(request, model);359 const { url, headers, apiName, safetySettings } = await getGoogleApiConfig(request, model);
359360
360 console.debug(`${apiName} TTS request`, { model, text, voice });361 console.debug(`${apiName} TTS request`, { model, text, voice });
361362
@@ -374,7 +375,7 @@ router.post('/generate-native-tts', async (request, response) => {
374 },375 },
375 },376 },
376 },377 },
377 safetySettings: GEMINI_SAFETY,378 safetySettings: safetySettings,
378 };379 };
379380
380 const result = await fetch(url, {381 const result = await fetch(url, {